使用单一方法获取 PortAudio 录制的数据
Get PortAudio recorded data with a single method
我正在使用 C++ 编写吉他调音器应用程序。我正在使用 PortAudio 来记录来自麦克风的数据。录制代码如果全部放在主class中,效果很好。但是,我宁愿在主 class 中有一个方法来检索记录的数据。我用所有 PortAudio 代码创建了一个单独的 class (recordaudio.cpp),但是当我从主 class 调用此 class 的 readStream 方法时,我收到消息:
Error number: -10000
Error message: PortAudio not initialized
PortAudio 已经在 "recordaudio.cpp" class 的构造函数中实例化了,所以我不确定为什么要这样说。
这里是主要的 class 调用 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.cppclass。这个想法是不断调用位于此 class.
中的 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 ) );
}
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
cout << "Now recording!!" << endl;
error:
Pa_Terminate();
所以就在 "now recording" 之后 - 你调用 PA_Terminate() 可能不是你想要的。 GOTO 是 evil 并且在这种情况下的标签让您误以为它只会在您调用 goto 错误时转到那里。它没有。标签只是一个标记,执行将愉快地继续通过它。
我正在使用 C++ 编写吉他调音器应用程序。我正在使用 PortAudio 来记录来自麦克风的数据。录制代码如果全部放在主class中,效果很好。但是,我宁愿在主 class 中有一个方法来检索记录的数据。我用所有 PortAudio 代码创建了一个单独的 class (recordaudio.cpp),但是当我从主 class 调用此 class 的 readStream 方法时,我收到消息:
Error number: -10000
Error message: PortAudio not initialized
PortAudio 已经在 "recordaudio.cpp" class 的构造函数中实例化了,所以我不确定为什么要这样说。
这里是主要的 class 调用 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.cppclass。这个想法是不断调用位于此 class.
中的 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 ) );
}
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
cout << "Now recording!!" << endl;
error:
Pa_Terminate();
所以就在 "now recording" 之后 - 你调用 PA_Terminate() 可能不是你想要的。 GOTO 是 evil 并且在这种情况下的标签让您误以为它只会在您调用 goto 错误时转到那里。它没有。标签只是一个标记,执行将愉快地继续通过它。