PortAudio:Pa_StartStream()在DLL中使用时会崩溃Game Maker

时间:2014-02-05 16:40:56

标签: c++ dll stream portaudio game-maker

我想通过使用DLL在Game Maker中使用PortAudio 我在C ++中创建了回调函数,并用它来计算传入样本流的频率。在DLL中我做了一些导出函数:一个用于启动流,一个用于关闭流,另一个用于获取回调生成的频率变量。
现在当我在Game Maker中调用PortAudioStart()函数时,游戏关闭时没有任何警告/错误/消息。我将MessageBox()放在代码行之间,以检查崩溃的来源。它显示了第一个,第二个和第三个,然后它崩溃了,甚至没有显示错误MessageBox。所以事实证明Pa_StartStream()引起了它。

现在我想知道:为什么会发生这种崩溃,我该如何解决呢? 注意:我通过让C ++程序调用它来测试这个DLL,在这种情况下,它完全按计划工作。

我使用GM8.0和NetBeans 7.3与Cygwin 4的gcc编译器。

开始和结束函数(省略全局变量的所有包含和定义):

#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);
P.S:如果有什么不清楚的地方,请问,我对C ++的了解并不是很出色。

0 个答案:

没有答案