C++ portaudio只采集一个样本?

C++ portaudio只采集一个样本?,c++,ubuntu,debugging,portaudio,C++,Ubuntu,Debugging,Portaudio,我目前正在使用portaudio开发一个记录的应用程序,我似乎在收集样本时遇到了一些问题。从我看到的情况来看,只存储了一个样本,并且只调用了一次回调,也就是说,即使变量NUM\u OF_SECONDS设置为30秒 我现在对我可以测试什么以及如何调试这个问题已经没有什么想法了,所以我来到这里,对如何调试我的问题有什么建议吗 代码如下: main.cpp: #include <record.h> int main() { record somethis; someth

我目前正在使用portaudio开发一个记录的应用程序,我似乎在收集样本时遇到了一些问题。从我看到的情况来看,只存储了一个样本,并且只调用了一次回调,也就是说,即使变量
NUM\u OF_SECONDS
设置为30秒

我现在对我可以测试什么以及如何调试这个问题已经没有什么想法了,所以我来到这里,对如何调试我的问题有什么建议吗

代码如下:

main.cpp:

#include <record.h>

int main()
{
    record  somethis;
    somethis.start_record();
    return 0;
}
#包括
int main()
{
记录一些这个;
开始记录();
返回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);

    }
};
#pragma一次
#包括//功能:COUT
#包括“portaudio.h”
#包括
#包括
#包括//功能:睡眠
#包括//功能:睡眠
#包括//功能:填充
#定义采样率(44100)
typedef浮样;
#定义NUM_秒30
#定义NUM_通道2
#定义样本0.0f
#定义PAU样本类型PA32
#为每个缓冲区定义帧(512)
#定义真(1==1)
#定义FALSE(!TRUE)
#将写入文件定义为TRUE
类型定义结构
{
整数帧索引;
int-maxFrameindex;
样本*记录样本;
}
paTestData;
课堂记录{
公众:
记录();
无效开始记录();
私人:
PaStreamParameters输入参数,
输出参数;
泛流*流;
PaError err=paNoError;
统计数据;
整数帧;
整数样本;
整数单位;
样本最大值,val;
双倍平均;
int recordCallback(const void*inputBuffer,void*outputBuffer,
未签名的长帧缓冲,
const Pastream CallbackTimeInfo*timeInfo,
PaStreamCallbackFlags状态标志,void*userData);
静态int-recordCallbackSub(常量void*inputBuffer,void*outputBuffer,
无符号长帧缓存,常量PaStreamCallbackTimeInfo*timeInfo,
PaStreamCallbackFlags状态标志,void*userData)
{
auto pThis=reinterpret_cast(userData);//获取此指针的值。
返回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;



}
#包括“record.h”
记录::记录()
{
std::cout totalFrames*NUM_通道;
numBytes=numSamples*sizeof(样本);
此->data.recordedSamples=新样本[numSamples];/*从现在起,recordedSamples将被初始化*/
if(this->data.recordedSamples==NULL)
{
std::cout您的第一次回拨

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-recordCallbackSub(常量void*inputBuffer,void*outputBuffer,
无符号长帧缓存,常量PaStreamCallbackTimeInfo*timeInfo,
PaStreamCallbackFlags状态标志,void*userData)
{
auto pThis=reinterpret_cast(userData);//获取此指针的值。
返回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;

    ....
}
int record::recordCallback(const void*inputBuffer,void*outputBuffer,
未签名的长帧缓冲,
const Pastream CallbackTimeInfo*timeInfo,
PaStreamCallbackFlags状态标志,void*userData)
{

std::请不要让问题只能用其中包含的信息来回答。回答问题不需要访问外部链接。你用的是什么语言?是
C
还是
C++
。请选择一个。我添加了代码并更改了标记@bolovIt似乎已经修复了它。我正在使用paex\record.c脚本portaudio提供的示例。我过去/现在仍然有点不确定userData的实际功能是什么?userData参数是c API(如Port Audio)的一个相当常见的功能,它的目的是让您将任意的、用户定义的信息传递给回调。您自己已经完成了这项工作,将指向类的指针传递给您的
recordCallbackSub
函数-允许您从静态函数获取成员函数。如果没有
void*userData
参数,这根本不可能。paex_record.c示例使用此机制将数据结构传递到回调中,但由于您已经在类中,因此可以使用成员variab相反,我直接告诉你。