2016-10-25 6 views
0

私はギターチューナーアプリケーションをC++で開発しています。私はPortAudioを使ってマイクからデータを記録しています。レコーディングコードは、すべてメインクラスに配置されていればうまく動作します。しかし、私はむしろ、記録されたデータを取り出すために、メインクラス内に単一のメソッドを持っています。私はすべてのPortAudioコードで別のクラス(recordaudio.cpp)を作成したが、私はメインクラスから、このクラスのreadStreamメソッドを呼び出すと、私はメッセージを取得:PortAudioで記録されたデータを1つの方法で取得する

エラー番号:-10000
エラーメッセージ:PortAudioは、すでに「recordaudio.cpp」クラスのコンストラクタでインスタンス化される

PortAudio

を初期化していないので、私はそれはそれを言っている理由はわかりません。ここ

getAudioStream(バッファ)メソッドを呼び出すメインクラスである:ここ

#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)); 
} 
+0

1)私は個人的にはコンストラクタではあまり必要としないでしょう。ポートオーディオを初期化して失敗を投げます(すべてのgotoが消えてしまいます)。そして、デストラクタでPa_Terminateを実行します。あなたはRAIIデザインを持っています。 2)どのコールが初期化されていないと報告していますか? – UKMonkey

+0

これを報告するのは、メインクラスのgetAudioStream()呼び出しです。 gotoはPortAudioの例に基づいていますが、私は今日後であなたの提案を試してみましょう。 –

+0

質問に続きます:サンプルコードでgotoを使用するサードパーティのコードをプロジェクトに追加しますか?いずれにせよ、 "getAudioStream()"はエラーをより明白にしました。 – UKMonkey

答えて

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

error: 
    Pa_Terminate(); 

だから "今すぐ録画" の後に - あなたはPA_Terminateを(呼び出し)は、おそらくないあなたが何を望みますか。 GOTOはevilであり、この場合のラベルは、あなたがgotoエラーと呼ばれる場合にのみそこに行くと思うようにあなたを混乱させました。それはしません。ラベルはちょうどマーカーであり、実行はそれを介して幸せに続きます。

+0

さて、それを知りませんでした。それが事実なら私は間違いなくそれらを取り除くでしょう –

+0

素晴らしい!私はgotoラベルを削除し、それは確かにうまくいった。 –

関連する問題