2016-06-16 4 views
0

PortAudioでサウンドアプリケーションを作成しています。私は主なコールバック関数に渡される個々のオシレータのデータを表す構造体の配列を持っています。PortAudioコールバック内の波形を加算する

1つの行に2つの波を合計して再生しようとするとうまくいきますが、forループでそれを実行しようとすると、任意に発振器を合計することができます。

だから、これは動作します:

*out = sinetable[(int)oscs[0].phase % TABLE_SIZE] * (oscs[0].amp/2) + sinetable[(int)oscs[1].phase % TABLE_SIZE] * (oscs[1].amp/2);

をしかし、これはそうではない:

for(int j = 0; j < 2; j++) 
    {  
    *out += sinetable[(int)oscs[j].phase % TABLE_SIZE] * (oscs[j].amp/2);      
    } 

私はちょうど発振器の任意の数を合計する方法が必要です。私はこれらの2つの方法が同等であると考えましたが、明らかにそうではありません。

ご迷惑をおかけして申し訳ありません。

編集: 完全なコードはここにある:

  #include <stdio.h> 
     #include <math.h> 
     #include "portaudio.h" 

     #define NUM_SECONDS (2) 
     #define SAMPLE_RATE (44100) 
     #define FRAMES_PER_BUFFER (0) // PA will select in it's own.. 

     #ifndef M_PI 
     #define M_PI (3.14159265) 
     #endif 

     #define TABLE_SIZE (4096) // < Hz/(sampling rate/table size) [line 53]] 
     float sinetable[TABLE_SIZE]; 

     typedef struct 
     { 
      float phase = 0; 
      float freq = 300; 
      float amp = 0.5; 
     } 
     Osc; 

     void initTable(){ 
      for(int i = 0; i < TABLE_SIZE; i++){ 

       sinetable[i] = sin(2 * M_PI * i/TABLE_SIZE); 
      } 
     } 

     /* This routine will be called by the PortAudio engine when audio is needed. 
     ** It may called at interrupt level on some machines so don't do anything 
     ** that could mess up the system like calling malloc() or free(). 
     */ 
     static int patestCallback(const void *inputBuffer, void *outputBuffer, 
            unsigned long framesPerBuffer, 
            const PaStreamCallbackTimeInfo* timeInfo, 
            PaStreamCallbackFlags statusFlags, 
            void *userData) 
     { 
      Osc *oscs = (Osc*)userData; 
      float *out = (float*)outputBuffer; 
      unsigned long i; 

      (void) timeInfo; /* Prevent unused variable warnings. */ 
      (void) statusFlags; 
      (void) inputBuffer; 


      for(i=0; i<framesPerBuffer; i++) 
      { 

       /* 
       for(int j = 0; j < 2; j++){  //this won't work... 
       *out += sinetable[(int)oscs[j].phase % TABLE_SIZE] * (oscs[j].amp/2);      
       } 
       */ 
       // but this does: 
       *out = sinetable[(int)oscs[0].phase % TABLE_SIZE] * (oscs[0].amp/2) + sinetable[(int)oscs[1].phase % TABLE_SIZE] * (oscs[1].amp/2);   

       oscs[0].phase += oscs[0].freq/(SAMPLE_RATE/(float)TABLE_SIZE);   
       oscs[1].phase += oscs[1].freq/(SAMPLE_RATE/(float)TABLE_SIZE); 

       *out++; 
      } 

      return paContinue; 
     } 



     /* 
      * This routine is called by portaudio when playback is done. 
      */ 
     static void StreamFinished(void* userData) 
     { 
      Osc *oscs = (Osc *) userData; 
      // printf("Stream Completed: %s\n", oscs->message); 
     } 

     /*******************************************************************/ 
     int main(void); 
     int main(void) 
     { 
      PaStreamParameters outputParameters; 
      PaStream *stream; 
      PaError err; 
      Osc oscs[5]; 
      int i; 
      oscs[1].freq = 400; oscs[2].freq = 500; oscs[3].freq = 600; oscs[4].freq = 700; 

      printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); 

      /* initialise sinusoidal wavetable */ 
      for(i=0; i<TABLE_SIZE; i++) 
      { 
       sinetable[i] = 2* M_PI * (i/TABLE_SIZE); //using this global table   
      } 
      // oscs.phase = 0; 

      initTable(); 

      err = Pa_Initialize(); 
      if(err != paNoError) goto error; 

      outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 
      if (outputParameters.device == paNoDevice) { 
       fprintf(stderr,"Error: No default output device.\n"); 
       goto error; 
      } 
      outputParameters.channelCount = 1;  /* mono output */ 
      outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ 
      outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; 
      outputParameters.hostApiSpecificStreamInfo = NULL; 

      err = Pa_OpenStream(
         &stream, 
         NULL, /* no input */ 
         &outputParameters, 
         SAMPLE_RATE, 
         FRAMES_PER_BUFFER, 
         paClipOff,  /* we won't output out of range samples so don't bother clipping them */ 
         patestCallback, 
         &oscs); 
      if(err != paNoError) goto error; 

      // sprintf(oscs.message, "No Message"); 
      err = Pa_SetStreamFinishedCallback(stream, &StreamFinished); 
      if(err != paNoError) goto error; 

      err = Pa_StartStream(stream); 
      if(err != paNoError) goto error; 

      printf("Play for %d seconds.\n", NUM_SECONDS); 
      Pa_Sleep(NUM_SECONDS * 1000); 

      err = Pa_StopStream(stream); 
      if(err != paNoError) goto error; 

      err = Pa_CloseStream(stream); 
      if(err != paNoError) goto error; 

      Pa_Terminate(); 
      printf("Test finished.\n"); 

      return err; 
     error: 
      Pa_Terminate(); 
      fprintf(stderr, "An error occured while using the portaudio stream\n"); 
      fprintf(stderr, "Error number: %d\n", err); 
      fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 
      return err; 
     } 

答えて

2

は、私は合計する前*outをゼロに勧告することができますか?

*out = 0; 
for(int j = 0; j < 2; j++) 
{  
    *out += sinetable[(int)oscs[j].phase % TABLE_SIZE] * (oscs[j].amp/2);      
} 

は、そうでない場合outにあったものは何でも合計で+=に感謝を巻きます。

*out = sinetable[(int)oscs[0].phase % TABLE_SIZE] * (oscs[0].amp/2) + 
     sinetable[(int)oscs[1].phase % TABLE_SIZE] * (oscs[1].amp/2); 

=outにあったものは何でも上書きされるため、この周りを取得します。

+0

ああ、そうです。もちろん、明らかになっているようです。 :) – oraz

関連する問題