使用单一方法获取PortAudio记录的数据

时间:2016-10-25 13:19:25

标签: c++ audio-streaming audio-recording portaudio

我正在使用c ++编写吉他调音器应用程序。我正在使用PortAudio来记录麦克风的数据。如果录制代码全部放在主类中,则录制代码效果很好。但是,我宁愿在主类中使用一个方法来检索记录的数据。我用所有的PortAudio代码创建了一个单独的类(recordaudio.cpp),但是当我从主类调用这个类的readStream方法时,我收到了消息:

  

错误编号:-10000
  错误消息:PortAudio未初始化

PortAudio已经在“recordaudio.cpp”类的构造函数中实例化了,所以我不确定为什么会这么说。

这是调用getAudioStream(buffer)方法的主类:

#include "autocorrelation.h"
#include "peakpicking.h"
#include "recordaudio.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <alsa/asoundlib.h>
#include <unistd.h>

#define SAMPLE_RATE 44100
#define WINDOW_SIZE 1024
#define WIN_HAMMING 1
#define WIN_HANN 2
#define WIN_SINE 3

using namespace std;

int main(){
    double max, average, val;
    double frequency=0;
    double period; 

    // Data buffers
    double* buffer = (double*) malloc(sizeof(double)*WINDOW_SIZE);
    double* buffer_snac = (double*) malloc(sizeof(double)*WINDOW_SIZE);

    // Instantiate  
    recordaudio audio = recordaudio();
    autocorrelation acf = autocorrelation(WINDOW_SIZE);
    peakpicking pick = peakpicking(buffer_snac, WINDOW_SIZE);

    while (true){
        audioStatus = audio.getAudioStream(buffer);

        // Autocorrelation function
        acf.autocorrelation_snac(buffer, buffer_snac);

        // Peak Picking
        period = pick.getPeriod();

        // Calculate frequency
        frequency = SAMPLE_RATE/period;
        cout  << "\r" << "frequency: " <<frequency << "  "  << flush;
    }
    audio.closeStream(); 

}

recordaudio.h文件

#ifndef RECORD_AUDIO_H
#define RECORD_AUDIO_H
#include "portaudio.h"

class recordaudio {

private:
    PaStreamParameters inputParameters;
    PaError err;
    PaStream *stream;

public:
    recordaudio();
    bool getAudioStream(double *buffer);
    void closeStream();
};

#endif

这是recordaudio.cpp类。我们的想法是不断调用此类中的getAudioStream(* buffer)方法。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <alsa/asoundlib.h>
#include <unistd.h>
#include <algorithm>
#include "recordaudio.h"

#define SAMPLE_RATE 44100
#define WINDOW_SIZE 1024
#define WIN_HAMMING 1
#define WIN_HANN 2
#define WIN_SINE 3

#define NUM_CHANNELS    (1)
/* #define DITHER_FLAG     (paDitherOff)  */
#define DITHER_FLAG     (0) /**/
/* Select sample format. */
#define PA_SAMPLE_TYPE  paFloat32
#define SAMPLE_SILENCE  (0.0f)
#define PRINTF_S_FORMAT "%.8f"


using namespace std;

recordaudio::recordaudio( ){
    err = Pa_Initialize();
    if( err != paNoError ) goto error;

    inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
    if (inputParameters.device == paNoDevice) {
      fprintf(stderr,"Error: No default input device.\n");
      goto error;
    }

    inputParameters.channelCount = NUM_CHANNELS;
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;
    inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
    inputParameters.hostApiSpecificStreamInfo = NULL;

    err = Pa_OpenStream(
              &stream,
              &inputParameters,
              NULL,     /* &outputParameters, */
              SAMPLE_RATE,
              WINDOW_SIZE,
              paClipOff,/* we won't output out of range samples so don't bother clipping them */
              NULL,     /* no callback, use blocking API */
              NULL );   /* no callback, so no callback userData */


    if( err != paNoError ) goto error;
    err = Pa_StartStream( stream );
    if( err != paNoError ) goto error;
    cout << "Now recording!!" << endl;

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 ) );
}

bool recordaudio::getAudioStream(double *buffer){
    err = Pa_ReadStream(stream, buffer, WINDOW_SIZE);
    if( err != paNoError ) goto error;
    return true;

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 false;


}

void recordaudio::closeStream(){
    err = Pa_CloseStream( stream );
    if( err != paNoError ) goto error;

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 ) );
}

1 个答案:

答案 0 :(得分:0)

    if( err != paNoError ) goto error;
    err = Pa_StartStream( stream );
    if( err != paNoError ) goto error;
    cout << "Now recording!!" << endl;

error:
    Pa_Terminate();

所以就在&#34;现在录制&#34; - 你打电话给PA_Terminate()可能不是你想要的。 GOTO是evil,在这种情况下,标签让你误以为如果你调用goto错误它只会去那里。它没有。标签只是一个标记,执行将很快继续通过它。