私は現在記録しているアプリケーションでportaudioを使っていますが、サンプルを収集する際に問題があるようです。私が見ることができるのは、格納されているサンプルが1つだけであり、変数NUM_OF_SECONDS
が30秒に設定されていても、コールバックは1回だけ呼び出されていることです。portaudioは1つのサンプルしか取っていませんか?
私は現在何がテストできるのか、どのようにこれをデバッグできるのかというアイデアが不足しているので、私はここで問題をデバッグする方法を提案していますか?
main.cppに:
#include <record.h>
int main()
{
record somethis;
somethis.start_record();
return 0;
}
record.h
#pragma once
#include <iostream> // Functionality: COUT
#include "portaudio.h"
#include <stdio.h>
#include <stdlib.h>
#include <chrono> //Functionality: Sleep
#include <thread> //Functionality: Sleep
#include <algorithm> //Functionality: fill_n
#define SAMPLE_RATE (44100)
typedef float SAMPLE;
#define NUM_SECONDS 30
#define NUM_CHANNELS 2
#define SAMPLE_SILENCE 0.0f
#define PA_SAMPLE_TYPE paFloat32
#define FRAMES_PER_BUFFER (512)
#define TRUE (1==1)
#define FALSE (!TRUE)
#define WRITE_TO_FILE TRUE
typedef struct
{
int frameIndex;
int maxFrameindex;
SAMPLE *recordedSamples;
}
paTestData;
class record {
public:
record();
void start_record();
private:
PaStreamParameters inputParameters,
outputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data;
int totalFrames;
int numSamples;
int numBytes;
SAMPLE max, val;
double average;
int recordCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData);
static int recordCallbackSub(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
auto pThis = reinterpret_cast<record*>(userData); // get back the this pointer.
return pThis->recordCallback(inputBuffer, outputBuffer,framesPerBuffer, timeInfo,statusFlags, nullptr);
}
};
record.cpp
#include "record.h"
record::record()
{
std::cout << "Record object made" << std::endl;
std::cout << "Portaudio Version: " << Pa_GetVersion() << std::endl;
this->data.maxFrameindex = this->totalFrames = NUM_SECONDS * SAMPLE_RATE;
this->data.frameIndex = 0;
this->numSamples = this->totalFrames * NUM_CHANNELS;
numBytes = numSamples * sizeof(SAMPLE);
this->data.recordedSamples = new SAMPLE[numSamples]; /* From now on, recordedSamples is initialised. */
if(this->data.recordedSamples == NULL)
{
std::cout << "Could not allocate record array" << std::endl;
exit(1);
}
for(int i=0; i<numSamples; i++)
{
this->data.recordedSamples[i] = 0;
}
int err = Pa_Initialize();
if(err == paNoError)
{
std::cout << "No error in init" << std::endl;
std::cout << "PortAudio init: "<< Pa_GetErrorText(err) << std::endl;
}
else
{
printf( "PortAudio error: %s\n", Pa_GetErrorText(err));
exit(1);
}
this->inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (this->inputParameters.device == paNoDevice) {
std::cout << "Error: No default input device" << std::endl;
exit(1);
}
this->inputParameters.channelCount = 1; /* stereo input */
this->inputParameters.sampleFormat = PA_SAMPLE_TYPE;
this->inputParameters.suggestedLatency = Pa_GetDeviceInfo(this->inputParameters.device)->defaultLowInputLatency;
this->inputParameters.hostApiSpecificStreamInfo = NULL;
std::cout << "Device name: " <<Pa_GetDeviceInfo(this->inputParameters.device)->name << std::endl;
std::cout << "Max inputChannels: " <<Pa_GetDeviceInfo(this->inputParameters.device)->maxInputChannels << std::endl;
}
int record::recordCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
std::cout << "Callback called" << std::endl;
this->data = (paTestData&) userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
SAMPLE *wptr = &this->data.recordedSamples[this->data.frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = this->data.maxFrameindex - this->data.frameIndex;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
//(void) userData;
if(framesLeft < framesPerBuffer)
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if(inputBuffer == NULL)
{
for(int i=0; i<framesToCalc; i++)
{
*wptr++ = SAMPLE_SILENCE; /* left */
if(NUM_CHANNELS == 2) *wptr++ = SAMPLE_SILENCE; /* right */
}
}
else
{
for(int i=0; i<framesToCalc; i++)
{
*wptr++ = *rptr++; /* left */
if(NUM_CHANNELS == 2) *wptr++ = *rptr++; /* right */
}
}
this->data.frameIndex += framesToCalc;
return finished;
}
void record::start_record()
{
err = Pa_OpenStream(
&this->stream,
&this->inputParameters,
NULL, /* &outputParameters, */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
&record::recordCallbackSub,
this);
if(err != paNoError)
{
std::cout << "Something wrong - open_stream check" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText(err) << std::endl;
exit(1);
}
this->err = Pa_StartStream(this->stream);
if(err != paNoError)
{
std::cout << "Something wrong in stream check" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText(err) << std::endl;
exit(1);
}
std::cout << "Waiting for playback to finish" << std::endl;
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", this->data.frameIndex); fflush(stdout);
}
if(err < 0)
{
std::cout << "error check with isStreamActive - something wrong" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText(err) << std::endl;
exit(1);
}
err = Pa_CloseStream(stream);
if(err != paNoError)
{
std::cout << "error check with close_stream- something wrong" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText(err) << std::endl;
exit(1);
}
std::cout << "Number of entries: " << sizeof(this->data.recordedSamples)/sizeof(this->data.recordedSamples[0]) << std::endl;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i=0; i<numSamples; i++)
{
val = this->data.recordedSamples[i];
std::cout << "i: " << i << " : "<< val << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if(val < 0) val = -val; /* ABS */
if(val > max)
{
max = val;
}
average += val;
}
average = average/(double)numSamples;
std::cout<<"sample max amplitude = " << max << std::endl;
std::cout<<"sample average = " << average << std::endl;
if (WRITE_TO_FILE)
{
FILE *fid;
fid = fopen("recorded.wav", "wb");
if(fid == NULL)
{
printf("Could not open file.");
}
else
{
fwrite(data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid);
fclose(fid);
printf("Wrote data to 'recorded.raw'\n");
}
}
std::cout << "Everythin done!" << std::endl;
}
更新:
ここコードです
私はいくつかのデバッグ通知から、コールバックは一度しか呼び出されておらず、返った後はストリームが非アクティブになるため、コールバック関数を呼び出すことが不可能になります。ストリームが非アクティブになるのはなぜですか?
質問を回答できるのは、その中に含まれている情報のみにしてください。 – bolov
あなたはどの言語を書いていますか?質問に答えるために外部リンクを訪問する必要はありませんか?それは 'C'か' C++ 'ですか?選択してください。 – bolov
コードを追加してタグを変更しました@bolov – Lamda