2016-12-27 3 views
0

私はおそらく何か愚かなことをしていますが、私が開発しているサウンドシステムで使用しているときにlibsndfileからデータの形式を取得していません。 sf_read_floatfは0より大きい値を返しますが、バッファ自体を見ると、データがゼロになっています。私もlibsamplerateを使用していますが、現時点では、オーディオファイルとポートオーディオの両方のサンプラーをテスト用に同じにしています。ポートオーディオとLibsndfileデータなし?

ポートオーディオコンストラクタ:

PortAudioSystem::PortAudioSystem(double sampleRate, PaDeviceIndex device, void * hostApiSpecificStreamInfo) { 
    this->m_masterVol = this->m_musicVol = this->m_sfxVol = 1.0f; 
    this->m_deltaTime = 0.0f; 
    this->audioStream = nullptr; 
    this->_hasPaError = false; 

    this->m_sampleRate = sampleRate; 

    PaStreamParameters streamParams; 
    streamParams.device = device; //set device to use 
    streamParams.hostApiSpecificStreamInfo = hostApiSpecificStreamInfo; 
    streamParams.sampleFormat = paFloat32; // 32bit float format 
    streamParams.suggestedLatency = 0.2; //200 ms ought to satisfy even the worst sound card 
    streamParams.channelCount = 2; //number of channels (1: mono, 2: left/right, etc) 

    int err = 0; 

    err = Pa_OpenStream(
     &this->audioStream, 
     0, // no input 
     &streamParams, 
     sampleRate, 
     paFramesPerBufferUnspecified, // let portaudio choose the buffersize 
     paNoFlag,/* no special modes (clip off, dither off) */ 
     PortAudioSystem::paCallbackCommon, 
     this 
    ); 

    if (err != paNoError) { 
     pushPaError(err, Pa_GetErrorText(err)); 
     this->audioStream = nullptr; 
    } 

    int src_err; 
    this->m_srcState = src_new(SRC_SINC_FASTEST,2,&src_err); //create a new sample rate converter 

    if (this->m_srcState == NULL) { 
     //src_error(this->m_srcState); 
     this->pushPaError(src_err, src_strerror(src_err)); 
    } 

    this->m_nextPlayID = 0; 
} 

ポートオーディオコールバック:

int PortAudioSystem::paCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { 
    this->m_deltaTime = (float)((double)framesPerBuffer/this->m_sampleRate); //get delta time based on sample rate and number of frames per buffer 
    if (this->m_playingAudioFiles.size() == 0) return paContinue; //if we dont have any playing audio files, skip. 

    AudioFrame::_2 *outFrame = (AudioFrame::_2*)outputBuffer; //convert the port audio buffer to an audio frame buffer. 

    //zero out the output buffer. 
    for (unsigned long zeroI = 0; zeroI < framesPerBuffer; zeroI++) { 
     outFrame[zeroI].left = 0.0f; 
     outFrame[zeroI].right = 0.0f; 
    } 

    //for (PlayingAudioFile playingfile : this->m_playingAudioFiles) playingfile.audioFile->Seek(playingfile.currentFrame); //seek to the current position of the file 

    AudioFrame::_2 *framesOut = new AudioFrame::_2[framesPerBuffer]; //create a buffer for frames out. 
    //float * fFramesOut = new float[framesPerBuffer * 2]; //create a float buffer for frames out (*2 for left and right channel) 

    //prep common data for sample rate conversion. 
    SRC_DATA src_data; 
    src_data.output_frames = framesPerBuffer; //set output frames to be the max output frames to have. 
    src_data.end_of_input = 0; //we are not at the end of the file (change for specific audio file system [function?]). 
    src_data.data_out = (float *)framesOut; //set our output frames to be the buffer that we created. 

    flow.lock(); //mutex lock 
    for (std::pair<long, PlayingAudioFile> entry : this->m_playingAudioFiles){ //for each playing audio file 
     if (entry.second.paused) continue; //if the audio file is paused, skip it. 

     PlayingAudioFile& playingfile = entry.second; 
     playingfile.audioFile->Seek(playingfile.currentFrame); //seek to the current position of the file 

     src_data.src_ratio = this->m_sampleRate/playingfile.audioFile->GetSampleRate(); //get the ratio of the sample rate conversion 

     if (src_data.src_ratio == 1) { //if we are 1 to 1, dont do sample rate conversion. 
      src_data.input_frames_used = src_data.output_frames_gen = (long)playingfile.audioFile->GetFrames(framesPerBuffer, (float *)framesOut); 
     } else { //otherwise convert to port audio system's sample rate. 
      //adjust the number of frames to read based on ratio. 
      long long framesToRead//; 
      /*if (fmod((double)framesPerBuffer, src_data.src_ratio) == 0) framesToRead = framesPerBuffer; 
      else framesToRead*/ = (framesPerBuffer/((long long)src_data.src_ratio));// + 2; 

      AudioFrame::_2* framesIn = new AudioFrame::_2[framesToRead]; //create a buffer for frames in. 
      //float * fFramesIn = new float[framesToRead * 2]; //create a float buffer to read in frames. (*2 for left and right audio channel) 
      src_data.data_in = (float *)framesIn; //set the frame in buffer 

      src_data.input_frames = (long)playingfile.audioFile->GetFrames(framesToRead, (float *)framesIn); //read the frames; //set the number of frames that were read 

      if (src_data.input_frames == 0) { 
       delete[] framesIn; //free up the frame in buffer to prevent memory leaks. 
       continue; //if we have no data, skip 
      } 

      src_reset(this->m_srcState); //reset the sample rate conversion state 
      int src_err = src_process(this->m_srcState, &src_data); //convert the sample rate 

      if (src_err != 0) this->pushPaError(src_err, src_strerror(src_err)); //if we have an error, push it back. 

      delete[] framesIn; //free up the frame in buffer 
     } 

     //AudioFrame::_2* framesOut = (AudioFrame::_2*) fFramesOut; //convert the float buffer to an audio frame buffer for easier access to the channels 

     for (unsigned long outFrameI = 0; outFrameI < src_data.output_frames_gen; outFrameI++) { //for each frame (based on how many frames were generated from conversion [possibly under framesPerBuffer]) 
      //individual frame data; 
      AudioFrame::_2 frame = framesOut[outFrameI]; 

      //adjust volume from master volume 
      frame.left *= this->m_masterVol; 
      frame.right *= this->m_masterVol; 

      //adjust volume 
      switch (playingfile.channel) { //based on sound channel 
      case eAT_Music: //if we are a music channel 
       frame.left *= this->m_musicVol; 
       frame.right *= this->m_musicVol; 
       break; 
      case eAT_SFX: //if we are a sfx channel 
       frame.left *= this->m_sfxVol; 
       frame.right *= this->m_sfxVol; 
       break; 
      } 

      if (frame.left != 0.0f){ //make sure we have data. 
       if (outFrame[outFrameI].left == 0.0f) { //if the output frame has no data 
        outFrame[outFrameI].left = frame.left; //set the audio 
       } else { //if the output frame has data 
        outFrame[outFrameI].left += frame.left; //mix the channels 
        outFrame[outFrameI].left /= 2; //ghetto way of making sure we dont clip? 
       } 
      } 
      if (frame.right != 0.0f){ //make sure we have data. 
       if (outFrame[outFrameI].right == 0.0f) { //if the output frame has no data 
        outFrame[outFrameI].right = frame.right; //set the audio 
       } else { //if the output frame has data 
        outFrame[outFrameI].right += frame.right; //mix the channels 
        outFrame[outFrameI].right /= 2; //ghetto way of making sure we dont clip? 
       } 
      } 
     } 

     playingfile.currentFrame += src_data.input_frames_used; //update the current position time based on how many frames were converted; 

     if (playingfile.currentFrame >= playingfile.endFrame && !playingfile.loop) { //if we are finnished playing. 
      //mark for removal. 
      m_stoppedAudioFiles.push_back(entry.first); 
     } else { 
      //loop the file 
      playingfile.currentFrame = playingfile.startFrame; 
     } 
    } 

    delete [] framesOut; 

    //removed stopped audio files. 
    while (m_stoppedAudioFiles.size() > 0) { 
     this->m_playingAudioFiles.erase(m_stoppedAudioFiles.back()); 
     m_stoppedAudioFiles.pop_back(); 
    } 

    flow.unlock(); //mutex unlock 

    return paContinue; //continue playback 
} 

AudioFile_Libsnd:

bool AudioFile_Libsnd::Seek(long long position){ 
    if (!this->_hasSfError) { 
     if (sf_seek(this->sndFile, position, SF_SEEK_SET) == -1) { 
      int err = sf_error(this->sndFile); 
      pushSfError(err, sf_error_number(err)); 
      return false; 
     } 
     return true; 
    } 
    return false; 
} 

long long AudioFile_Libsnd::GetFrames(long long framesToRead, float buff[]){ 
    if (this->_hasSfError) return 0; 

    long long framesRead = sf_readf_float(this->sndFile, buff, framesToRead); 

    return framesRead; 
} 

bool AudioFile_Libsnd::GetFrame(float* frame) { 
    return sf_readf_float(this->sndFile, frame, 1) == 1; 
} 

AudioFrame :: _ 2:

struct _2 { 
     float left; 
     float right; 

     _2() : left(0.0f), right(0.0f) {} 
    }; 

PlayingAudioFile:

struct PlayingAudioFile { 
    IAudioFile* audioFile; 
    long long currentFrame; 
    long long startFrame; 
    long long endFrame; 
    bool loop; 
    bool paused; 
    EAudioChannel channel; 
}; 

私は私が正しくバッファを構築していますが、私は試してみましたと信じて...私は、全体のコードは一種の長いです知っているが、私は現在、私が間違ってやっているのか分かりません純粋な浮動小数点ポインタは、両方とも定義され、新しいもので作成され、動作しませんでした。私はまた、フレームごとにループをして、単一の浮動小数点数に保存しようとしましたが、明らかに変数の周りにスタックを投げてしまったため、壊れたエラーでした...助けがあれば幸いです。

答えて

0

修正済みです。私は馬鹿にしていた。 ここでこの権利は、犯人である:

if (playingfile.currentFrame >= playingfile.endFrame && !playingfile.loop) { //if we are finnished playing. 
     //mark for removal. 
     m_stoppedAudioFiles.push_back(entry.first); 
    } else { 
     //loop the file 
     playingfile.currentFrame = playingfile.startFrame; 
    } 

は、それが開始に現在のフレームを設定したため「(playingsource.currentFrame> = playingsource.endFrame & & playingsource.loop)であればそうでない」を「他」に変更毎回フレーム

関連する問題