My M4 loopback: Line out 3 to Line in 3, TRS balanced. 2.5Vrms.No, the screenshot is for single ended loopback only.
Monitor out #2 RCA single ended to TRS line-in #4 with -IN tied to ground. Full SE output signal which is around 2.5Vrms
My M4 loopback: Line out 3 to Line in 3, TRS balanced. 2.5Vrms.No, the screenshot is for single ended loopback only.
Monitor out #2 RCA single ended to TRS line-in #4 with -IN tied to ground. Full SE output signal which is around 2.5Vrms
What puzzles me is that if I adjust the signal output to match the -12.4 dBFS, the THD+N is worse than yours. I was using a multimeter capable of measuring Vrms at 1KHz. I don't know how you measured your RCA output Vrms and if 2.5Vrms is accurate.Yes I expect cleaner, lower THD loopback with balanced connections. The noise level is almost the same though.
What puzzles me is that if I adjust the signal output to match the -12.4 dBFS, the THD+N is worse than yours. I was using a multimeter capable of measuring Vrms at 1KHz. I don't know how you measured your RCA output Vrms and if 2.5Vrms is accurate.
The one I bought 2 months ago is the new revision. I have no issue with ryzen threadripper (old version) on the latest Win10 Pro desktop.Dear all, wanted to confirm that MOTU obviously now ships the new revision of the m4, as first made public by Evgeniy in the post above. have inspected a newly bought unit, seems the same as above.
win10 drivers (asio and mme/ks/dx) seem not to play so well on a ryzen mobile 4800u apu notebook, will have to do some many more tests. a rme fireface uc plays stable as a rock on the same notebook.
Evgeniy: did you encounter driver problems (=cracks and pops) with this new revision of the m4, if tested on win10?
Cheerio!
Evgeniy: did you encounter driver problems (=cracks and pops) with this new revision of the m4, if tested on win10?
Cheerio!
Ok just opened my unit, IC400 and IC401 are THS4521, I'll try to upgrade it to THS4531. U400 and U402 has 45U marking on them.Anyone who knows the value of U400, U402, IC400, IC401? TIA
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
HMODULE MotuDLL;
FARPROC MSeriesInit;
FARPROC MSeriesGetNumDevices;
FARPROC MSeriesGetCurrentState;
FARPROC MSeriesGetDiagnostics;
FARPROC MSeriesFree;
int motulib_initialized = 0;
void InitMotuLib (void);
void DeInitMotuLib (void);
void Error (char *s, ...)
{
va_list args;
va_start(args,s);
vprintf(s,args);
va_end(args);
fflush(stdout);
exit(-1);
}
void InitMotuLib (void)
{
int r;
static int motulib_atexit_installed = 0;
if (motulib_initialized)
return;
MotuDLL = LoadLibraryA("C:\\Program Files (x86)\\MOTU\\CoreUAC\\MSeriesLib.dll");
if (!MotuDLL)
Error("Error: Failed to LoadLibraryA MSeriesLib.dll!\n");
MSeriesInit = GetProcAddress(MotuDLL, "_MSeriesInit@0");
MSeriesFree = GetProcAddress(MotuDLL, "_MSeriesFree@0");
MSeriesGetNumDevices = GetProcAddress(MotuDLL, "_MSeriesGetNumDevices@4");
MSeriesGetCurrentState = GetProcAddress(MotuDLL, "_MSeriesGetCurrentState@24");
MSeriesGetDiagnostics = GetProcAddress(MotuDLL, "_MSeriesGetDiagnostics@20");
if (!MSeriesInit || !MSeriesFree || !MSeriesGetNumDevices || !MSeriesGetDiagnostics || !MSeriesGetCurrentState)
Error("Error: GetProcAddress failed for a required function from MSeriesLib.dll\n");
r = MSeriesInit();
if (r != 0)
Error("Error: MSeriesInit call failed (return value %i)\n", r);
// program will crash on exit if MSeriesLib isn't deinitialized first
if (!motulib_atexit_installed)
{
atexit(DeInitMotuLib);
motulib_atexit_installed = 1;
}
// must always wait a bit before calling any MSeriesLib functions after
// library init, or program will crash!
Sleep(100);
motulib_initialized = 1;
}
void DeInitMotuLib (void)
{
if (!motulib_initialized)
return;
MSeriesFree();
Sleep(100);
FreeLibrary(MotuDLL);
motulib_initialized = 0;
}
int main (int argc, char **argv)
{
int r, numdevices, devnum;
int samplerate, buffersize, xso1x, waveinenables, waveoutenables;
int MinUSBLat, MaxUSBLat, MinCBus, MaxCBus;
int bufferStatusOk = 1;
int latMax = 0;
// fancy Win32 console crap
HANDLE constdout,constdin;
CONSOLE_SCREEN_BUFFER_INFO csbnfo;
int conw,conh,startx,starty,visw,vish,conbufsz,x,y;
CHAR_INFO *conbuf;
COORD incoord,insize,zero;
SMALL_RECT outcoord;
INPUT_RECORD inrec;
int conread;
if (argc < 2)
Error("Usage: usbstats <devnum>\n");
InitMotuLib();
MSeriesGetNumDevices(&numdevices);
if (numdevices <= 0)
Error("Error: MSeriesGetNumDevices returned <=0 devices\n");
devnum = atoi(argv[1]);
if (devnum < 1 || devnum > numdevices)
Error("Error: Bad device number on command line (only %i device%s present)\n", numdevices, numdevices==1 ? "" : "s");
devnum -= 1;
// more fancy Win32 console crap
constdin = GetStdHandle(STD_INPUT_HANDLE);
constdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (constdin == NULL || constdout == NULL)
Error("Error: Failed to get stdin/stdout console handles\n");
if (!GetConsoleScreenBufferInfo(constdout, &csbnfo))
Error("Error: GetConsoleScreenBufferInfo call failed\n");
conw = csbnfo.dwSize.X;
conh = csbnfo.dwSize.Y;
startx = csbnfo.srWindow.Left;
starty = csbnfo.srWindow.Right;
visw = csbnfo.srWindow.Right-csbnfo.srWindow.Left+1;
vish = csbnfo.srWindow.Bottom-csbnfo.srWindow.Top+1;
conbufsz = visw*vish;
conbuf = malloc(sizeof(CHAR_INFO)*conbufsz);
if (!conbuf)
Error("Error: Failed to allocate memory for character buffer\n");
memset(conbuf,0,conbufsz*sizeof(CHAR_INFO));
zero.X = zero.Y = 0;
incoord.X = incoord.Y = 0;
insize.X = visw; insize.Y = vish;
outcoord.Left = outcoord.Top = 0;
outcoord.Right = csbnfo.srWindow.Right;
outcoord.Bottom = csbnfo.srWindow.Bottom;
for (;;)
{
MSeriesGetCurrentState(devnum, &samplerate, &buffersize, &xso1x, &waveinenables, &waveoutenables);
MSeriesGetDiagnostics(devnum, &MinUSBLat, &MaxUSBLat, &MinCBus, &MaxCBus);
// formula straight from the C# UI applet
// latMax = Math.Max((oMaxUSBLat - 1) * 125, 125);
latMax = (MaxUSBLat-1)*125;
if (125 > latMax)
latMax = 125;
// formula straight from the C# UI applet
// bufferStatusOk = 1.2 * ((double) this.curBufferSize / (double) this.curSampleRate) > ((double) latMax + (double) oMaxCBus) / 1000000.0;
bufferStatusOk = 1.2f * ((double)buffersize / (double)samplerate) > ((double)latMax + (double)MaxCBus) / 1000000.0f;
SetConsoleCursorPosition(constdout, zero);
WriteConsoleOutput(constdout, conbuf, insize, incoord, &outcoord);
printf("press ESC to exit\n"\
"\n"\
"device=%i samplerate=%i buffersize=%i xso1x=%i wienables=%i woenables=%i\n"\
"MinUSBLat=%i MaxUSBLat=%i MinCBus=%i MaxCBus=%i\n"\
"\n"\
"%s\n",
devnum, samplerate, buffersize, xso1x, waveinenables, waveoutenables,
MinUSBLat, MaxUSBLat, MinCBus, MaxCBus,
bufferStatusOk ? "" : "/!\\ BUFFER SIZE WARNING /!\\");
fflush(stdout);
Sleep(50);
PeekConsoleInput(constdin, &inrec, 1, &conread);
if (conread)
{
if (inrec.EventType == KEY_EVENT)
{
if (inrec.Event.KeyEvent.bKeyDown == TRUE && inrec.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
break;
}
}
FlushConsoleInputBuffer(constdin);
}
free(conbuf);
DeInitMotuLib();
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
HMODULE MotuDLL;
FARPROC MSeriesInit;
FARPROC MSeriesGetNumDevices;
FARPROC MSeriesGetDeviceInfo;
FARPROC MSeriesSendTHD_TestSignalToOutputs;
FARPROC MSeriesFree;
FARPROC MSeriesStartAudio;
FARPROC MSeriesStopAudio;
int motulib_initialized = 0;
void InitMotuLib (void);
void DeInitMotuLib (void);
void Error (char *s, ...)
{
va_list args;
va_start(args,s);
vprintf(s,args);
va_end(args);
fflush(stdout);
exit(-1);
}
void InitMotuLib (void)
{
int r;
static int motulib_atexit_installed = 0;
if (motulib_initialized)
return;
MotuDLL = LoadLibraryA("C:\\Program Files (x86)\\MOTU\\CoreUAC\\MSeriesLib.dll");
if (!MotuDLL)
Error("Error: Failed to LoadLibraryA MSeriesLib.dll!\n");
MSeriesInit = GetProcAddress(MotuDLL, "_MSeriesInit@0");
MSeriesFree = GetProcAddress(MotuDLL, "_MSeriesFree@0");
MSeriesGetNumDevices = GetProcAddress(MotuDLL, "_MSeriesGetNumDevices@4");
MSeriesSendTHD_TestSignalToOutputs = GetProcAddress(MotuDLL, "_MSeriesSendTHD_TestSignalToOutputs@12");
MSeriesStartAudio = GetProcAddress(MotuDLL, "_MSeriesStartAudio@4");
MSeriesStopAudio = GetProcAddress(MotuDLL, "_MSeriesStopAudio@4");
MSeriesGetDeviceInfo = GetProcAddress(MotuDLL, "_MSeriesGetDeviceInfo@16");
if (!MSeriesInit || !MSeriesFree || !MSeriesGetNumDevices
|| !MSeriesSendTHD_TestSignalToOutputs
|| !MSeriesStartAudio || !MSeriesStopAudio
|| !MSeriesGetDeviceInfo)
Error("Error: GetProcAddress failed for a required function from MSeriesLib.dll\n");
r = MSeriesInit();
if (r != 0)
Error("Error: MSeriesInit call failed (return value %i)\n", r);
// program will crash on exit if MSeriesLib isn't deinitialized first
if (!motulib_atexit_installed)
{
atexit(DeInitMotuLib);
motulib_atexit_installed = 1;
}
// must always wait a bit before calling any MSeriesLib functions after
// library init, or program will crash!
Sleep(100);
motulib_initialized = 1;
}
void DeInitMotuLib (void)
{
if (!motulib_initialized)
return;
MSeriesFree();
Sleep(100);
FreeLibrary(MotuDLL);
motulib_initialized = 0;
}
int main (int argc, char **argv)
{
int r, numdevices, devnum, outputs;
char devver[32], devser[32], devname[32];
int duration;
double floatdur;
if (argc < 3)
Error("Usage: thdtest <devnum> <duration>\n");
InitMotuLib();
MSeriesGetNumDevices(&numdevices);
if (numdevices <= 0)
Error("Error: MSeriesGetNumDevices returned <=0 devices\n");
devnum = atoi(argv[1]);
if (devnum < 1 || devnum > numdevices)
Error("Error: Bad device number on command line (only %i device%s present)\n", numdevices, numdevices==1 ? "" : "s");
devnum -= 1;
duration = atoi(argv[2]);
if (duration < 1 || duration > 10)
Error("Error: Bad duration parm on command line (should be 1 to 10)\n");
r = MSeriesGetDeviceInfo(devnum, devver, devser, devname);
if (r != 0)
Error("Error: MSeriesGetDeviceInfo failed (code %i)\n", r);
if (!strcmp(devname, "M4"))
outputs = 4;
else if (!strcmp(devname, "M2"))
outputs = 2;
else
Error("Error: MSeriesGetDeviceInfo returned unknown device type \"%s\"\n", devname);
MSeriesStartAudio(devnum);
Sleep(100);
floatdur = duration;
MSeriesSendTHD_TestSignalToOutputs(devnum, floatdur);
Sleep(duration*1000*outputs+100);
MSeriesStopAudio(devnum);
Sleep(100);
DeInitMotuLib();
return 0;
}
LIBRARY MSERIESLIB
EXPORTS
??0DynamicRangeProcessor@@QAE@NHHH_N@Z
??0DynamicRangeTestSignal@@QAE@NHNNNHH@Z
??0DynamicRange_SequentialSignalGenerator@@QAE@NHNNNHHH_N@Z
??0GateTriggeredSignalProcessor@@QAE@NHN_NV?$unique_ptr@VSignalProcessor@@U?$default_delete@VSignalProcessor@@@std@@@std@@@Z
??0SignalDelay@@QAE@NHHV?$unique_ptr@VSignalGenerator@@U?$default_delete@VSignalGenerator@@@std@@@std@@@Z
??0SignalGenerator@@QAE@ABV0@@Z
??0SignalGenerator@@QAE@XZ
??0SignalProcessor@@QAE@ABV0@@Z
??0SignalProcessor@@QAE@XZ
??0SineStimulus@@QAE@NHN@Z
??0SineStimulus@@QAE@NHNNN@Z
??0THDPlusN_KernelWrapper@@QAE@MHNH@Z
??0THDPlusN_SequentialSignalGenerator@@QAE@NHHH_N@Z
??0THDPlusN_TestSignal@@QAE@NHH@Z
??1DynamicRangeProcessor@@UAE@XZ
??1DynamicRangeTestSignal@@UAE@XZ
??1DynamicRange_SequentialSignalGenerator@@QAE@XZ
??1GateTriggeredSignalProcessor@@UAE@XZ
??1SignalDelay@@UAE@XZ
??1SignalGenerator@@UAE@XZ
??1SignalProcessor@@UAE@XZ
??1SineStimulus@@QAE@XZ
??1THDPlusN_KernelWrapper@@UAE@XZ
??1THDPlusN_SequentialSignalGenerator@@QAE@XZ
??1THDPlusN_TestSignal@@UAE@XZ
??4SignalGenerator@@QAEAAV0@ABV0@@Z
??4SignalProcessor@@QAEAAV0@ABV0@@Z
??4SineStimulus@@QAEAAV0@ABV0@@Z
??_7DynamicRangeProcessor@@6B@
??_7DynamicRangeTestSignal@@6B@
??_7GateTriggeredSignalProcessor@@6B@
??_7SignalDelay@@6B@
??_7SignalGenerator@@6B@
??_7SignalProcessor@@6B@
??_7THDPlusN_KernelWrapper@@6B@
??_7THDPlusN_TestSignal@@6B@
?genSignal@DynamicRangeTestSignal@@UAEXPAM@Z
?genSignal@DynamicRange_SequentialSignalGenerator@@QAEXHPAM@Z
?genSignal@SignalDelay@@UAEXPAM@Z
?genSignal@THDPlusN_SequentialSignalGenerator@@QAEXHPAM@Z
?genSignal@THDPlusN_TestSignal@@UAEXPAM@Z
?getDynamicRange@DynamicRangeProcessor@@QAENXZ
?getMaxSignalLevelDB@GateTriggeredSignalProcessor@@QBENXZ
?getOutputSamples@SineStimulus@@QAEXPAM@Z
?getProcessor@GateTriggeredSignalProcessor@@QAEPAVSignalProcessor@@XZ
?getSignalLevel@DynamicRangeProcessor@@QAENXZ
?getTHDPlusN@THDPlusN_KernelWrapper@@QBENXZ
?linearAmplitudeForRelativeLevel@SineStimulus@@SANNNN@Z
?processBuffer@DynamicRangeProcessor@@UAEXPAM@Z
?processBuffer@GateTriggeredSignalProcessor@@QAEXPAMAA_N@Z
?processBuffer@GateTriggeredSignalProcessor@@UAEXPAM@Z
?processBuffer@THDPlusN_KernelWrapper@@UAEXPAM@Z
_MSeriesAnalogTestSequenceInit@8
_MSeriesClientAudio@8
_MSeriesDoTHDLoopback@20
_MSeriesEnableLowLatencyMode@8
_MSeriesFixedOutput@8
_MSeriesFree@0
_MSeriesGetCurrentState@24
_MSeriesGetDevice@8
_MSeriesGetDeviceInfo@16
_MSeriesGetDiagnostics@20
_MSeriesGetDriverInfo@24
_MSeriesGetDriverVersion@4
_MSeriesGetNumDevices@4
_MSeriesGetRecordedTestSignals@12
_MSeriesGetTestSequenceState@8
_MSeriesInit@0
_MSeriesInitAnalogTestSequenceConfig@4
_MSeriesInputMonitor@4
_MSeriesLatencyTest@8
_MSeriesMeasureInputDynamicRange@24
_MSeriesMeasureInputTHD@16
_MSeriesPlaySineWave@12
_MSeriesRestartDeviceIntoDFUMode@4
_MSeriesSendDynamicRangeTestSignalToOutputs@20
_MSeriesSendTHD_TestSignalToOutputs@12
_MSeriesSendTestSequenceMessage@12
_MSeriesSendVendorControlTransfer@28
_MSeriesSetHostBufferSize@8
_MSeriesSetSampleRate@8
_MSeriesSetWaveInEnables@8
_MSeriesSetWaveOutEnables@8
_MSeriesStartAudio@4
_MSeriesStopAudio@4
_MSeriesTestDLL@0
_RegisterGUINotificationCallback@4
My Motu M4, bought last june with firmware 2.00, seems to invert polarity on the balanced outputs. Has anyone else seen this issue?