gpt4 book ai didi

c++ - portaudio 只取一个样本?

转载 作者:搜寻专家 更新时间:2023-10-31 02:08:45 27 4
gpt4 key购买 nike

我目前正在使用带有录音应用程序的 portaudio,我似乎在收集样本时遇到了一些问题。据我所知,只有一个样本被存储,回调只被调用一次,仅此而已,即使变量 NUM_OF_SECONDS 设置为 30 秒。

我目前对可以测试的内容以及如何调试它一无所知,所以我来到这里,关于如何调试我的问题有什么建议吗?

代码如下:

主要.cpp:

#include <record.h>

int main()
{
record somethis;
somethis.start_record();
return 0;
}

记录.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);

}
};

记录.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;



}

更新:

我从一些调试通知中注意到回调只被调用一次,在它返回后,流变为非事件状态,因此无法调用回调函数。为什么流变为非事件状态?

最佳答案

你的第一个回调

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

}

调用你的第二个回调

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;

....
}

userData 参数设置为 nullptr。然后,您将 nullptr 转换为 paTestData& 并将您的 data 成员变量设置为结果,我怀疑您不打算这样做。

删除 this->data = (paTestData&) userData; 行。

关于c++ - portaudio 只取一个样本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47111790/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com