Я хочу использовать PortAudio в Game Maker с помощью DLL.
Я сделал функцию обратного вызова в C ++ и использовал ее для вычисления частоты входящего потока выборки. В DLL я сделал несколько функций экспорта: одну, которая инициирует поток, одну, которая закрывает поток, и одну, которая получает переменную частоты, сгенерированную обратным вызовом.
Теперь, когда я вызвал функцию PortAudioStart () в Game Maker, игра закрылась без каких-либо предупреждений / ошибок / сообщений. Я поместил MessageBox () между строками кода, чтобы проверить, что было причиной сбоя. Он показал первый, второй и третий, а затем он упал, даже не показывая ошибку MessageBox. Так что оказалось, что Pa_StartStream () вызвал это.
Теперь я задаюсь вопросом: почему происходит этот сбой, и как я могу это исправить?
Примечание: я протестировал эту DLL, позволив программе на C ++ вызывать ее, и в этом случае она работала полностью, как и планировалось.
Я использую GM8.0 и NetBeans 7.3 с компилятором gcc из Cygwin 4.
Функции начала и окончания (исключая все включения и определения глобальных переменных):
#define GMEXPORT extern "C" __declspec (dllexport)
GMEXPORT double __cdecl PortAudioStart() {
err = Pa_Initialize();
if( err != paNoError ) goto error;
MessageBoxA(NULL, "1", "PortAudio DLL", MB_ICONINFORMATION);
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
goto error;
}
inputParameters.channelCount = 1; /* mono input */
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
MessageBoxA(NULL, "2", "PortAudio DLL", MB_ICONINFORMATION);
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, //&outputParameters
SAMPLE_RATE,
FRAMES_PER_BUFFER,
0,
PaCallback,
NULL );
if( err != paNoError ) goto error;
MessageBoxA(NULL, "3", "PortAudio DLL", MB_ICONINFORMATION);
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
MessageBoxA(NULL, "4", "PortAudio DLL", MB_ICONINFORMATION);
return 1;
error:
MessageBoxA(NULL, "Apparently it doesn't work!", "PortAudio DLL", MB_ICONINFORMATION);
Pa_Terminate();
return 0;
}GMEXPORT double __cdecl PortAudioEnd() {
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
return 1;
error:
MessageBoxA(NULL, "Apparently it doesn't work!", "PortAudio DLL", MB_ICONINFORMATION);
Pa_Terminate();
return 0;
}
GMEXPORT double __cdecl getFreq()
{
if (Pa_IsStreamStopped(stream) == 0)
{
return frequency; // this variable is constantly changed in the callback function
}
else
{
return 0;
}
}
void calculateFreq(bool sign)
{
unsigned int j;
bool check;
diffsamp = maxsamp - minsamp;
if (!sign)
{
diffsampmax = max((diffsampmax*.85), (double)diffsamp);
maxsamp = 0;
}
if (sign)
{
diffsampmax = max((diffsampmax*.85), (double)diffsamp);
minsamp = 0;
}
check = ( diffsamp > max(25.0,diffsampmax*.90) );
if (sign == lastsign)
{
check = false;
}
if (check)
{
if (timepassed - peaks[0] < 500)
{
for ( j=numpeaks-1; j>0; j-- )
{
peaks[j] = peaks[j-1];
}
}
else
{
for ( j=0; j<numpeaks; j++ )
{
peaks[j] = 0;
}
}
peaks[0] = timepassed;
double diff = peaks[0]-peaks[numpeaks-1];
double peaktime = diff/(numpeaks-1)*2; //*2 because maxdiff is at +>- and ->+
frequency = 1/((double)peaktime/(double)SAMPLE_RATE);
if (peaks[numpeaks-1] <= 0 || frequency < 20) frequency = 0;
lastsign = sign;
}
}
static int PaCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
const SAMPLE *in = (const SAMPLE*)inputBuffer;
unsigned int i;
unsigned int j;
(void) timeInfo; // Prevent unused variable warnings.
(void) statusFlags;
(void) userData;
SAMPLE samp;
if( inputBuffer == NULL )
{
//nothing happens
}
else
{
for( i=0; i<framesPerBuffer; i++ )
{
timepassed += 1;
samp = *in++;
changed = false;
if (samp > 0)
{
if (!sign)
{
sign = true;
changed = true;
}
maxsamp = max(maxsamp,samp);
}
else
{
if (sign)
{
sign = false;
changed = true;
}
minsamp = min(minsamp,samp);
}
if (changed)
{
calculateFreq(sign);
}
}
}
return paContinue;
}
GML:
//// Script: pa_init()
globalvar _pa_freq,_pa_start,_pa_end;
var dll_name;
dll_name = "c:\Users\<Username>\Documents\NetBeansProjects\GMDLLtest\dist\Debug\Cygwin_4.x-Windows\libGMDLLtest.dll";
_pa_freq = external_define(dll_name, "getFreq", dll_cdecl, ty_real, 0);
_pa_start = external_define(dll_name, "PortAudioStart", dll_cdecl, ty_real, 0);
_pa_end = external_define(dll_name, "PortAudioEnd", dll_cdecl, ty_real, 0);
////--------------------------------------------------------------------------------
//// Script: pa_start()
return external_call(_pa_start);
////--------------------------------------------------------------------------------
//// Script: pa_end()
return external_call(_pa_end);
////--------------------------------------------------------------------------------
//// Script: pa_freq()
return external_call(_pa_freq);
П.С .: Если что-то неясно, пожалуйста, спросите, мои знания C ++ на самом деле не выдающиеся.
Задача ещё не решена.
Других решений пока нет …