简体   繁体   English

RtAudio-播放wav文件中的样本

[英]RtAudio - Playing samples from wav file

I am currently trying to learn audio programming. 我目前正在尝试学习音频编程。 My goal is to open a wav file, extract everything and play the samples with RtAudio. 我的目标是打开一个wav文件,提取所有内容并使用RtAudio播放样本。

I made a WaveLoader class which let's me extract the samples and meta data. 我制作了一个WaveLoader类,让我提取示例和元数据。 I used this guide to do that and I checked that everything is correct with 010 editor. 我使用了指南,并使用010编辑器检查了所有内容是否正确。 Here is a snapshot of 010 editor showing the structure and data. 这是010编辑器的快照,显示了结构和数据。

010编辑器

And this is how i store the raw samples inside WaveLoader class: 这就是我将原始样本存储在WaveLoader类中的方式:

        data = new short[wave_data.payloadSize]; // - Allocates memory size of chunk size

        if (!fread(data, 1, wave_data.payloadSize, sound_file))
        {
            throw ("Could not read wav data");
        }

If i print out each sample I get : 1, -3, 4, -5 ... which seems ok. 如果我打印出每个样本,我会得到:1,-3,4,-5 ...看起来还可以。

The problem is that I am not sure how I can play them. 问题是我不确定如何演奏。 This is what I've done: 这是我所做的:

/*
 * Using PortAudio to play samples
 */
bool Player::Play() 
{
    ShowDevices();
    rt.showWarnings(true);

    RtAudio::StreamParameters oParameters; //, iParameters;
    oParameters.deviceId = rt.getDefaultOutputDevice();
    oParameters.firstChannel = 0;
    oParameters.nChannels = mAudio.channels;

    //iParameters.deviceId = rt.getDefaultInputDevice();
    //iParameters.nChannels = 2;

    unsigned int sampleRate = mAudio.sampleRate;

    // Use a buffer of 512, we need to feed callback with 512 bytes everytime!
    unsigned int nBufferFrames = 512;

    RtAudio::StreamOptions options;
    options.flags = RTAUDIO_SCHEDULE_REALTIME;
    options.flags = RTAUDIO_NONINTERLEAVED;

    //&parameters, NULL, RTAUDIO_FLOAT64,sampleRate, &bufferFrames, &mCallback, (void *)&rawData

    try {
        rt.openStream(&oParameters, NULL, RTAUDIO_SINT16, sampleRate, &nBufferFrames, &mCallback, (void*) &mAudio);
        rt.startStream();
    }
    catch (RtAudioError& e) {
        std::cout << e.getMessage() << std::endl;
        return false;
    }
    return true;
}

/*
* RtAudio Callback
*
*/
int mCallback(void * outputBuffer, void * inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void * userData)
{
    unsigned int i = 0;
    short *out = static_cast<short*>(outputBuffer);
    auto *data = static_cast<Player::AUDIO_DATA*>(userData);

    // if i is more than our data size, we are done!
    if (i > data->dataSize) return 1;

    // First time callback is called data->ptr is 0, this means that the offset is 0
    // Second time data->ptr is 1, this means offset = nBufferFrames (512) * 1 = 512
    unsigned int offset = nBufferFrames * data->ptr++;

    printf("Offset: %i\n", offset);
    // First time callback is called offset is 0, we are starting from 0 and looping nBufferFrames (512) times, this gives us 512 bytes
    // Second time, the offset is 1, we are starting from 512 bytes and looping to 512 + 512 = 1024 
    for (i = offset; i < offset + nBufferFrames; ++i)
    {
        short sample = data->rawData[i]; // Get raw sample from our struct
        *out++ = sample;                // Pass to output buffer for playback

        printf("Current sample value: %i\n", sample);       // this is showing 1, -3, 4, -5 check 010 editor
    }

    printf("Current time: %f\n", streamTime);
    return 0;
}

Inside callback function, when I print out sample values I get exactly like 010 editor? 在回调函数内部,当我打印出样本值时,我得到的像是010编辑器吗? Why isnt rtaudio playing them. 为什么不是rtaudio播放它们。 What is wrong here? 怎么了 Do I need to normalize sample values to between -1 and 1? 我是否需要将样本值标准化为-1和1之间?

Edit: The wav file I am trying to play: 编辑:我正在尝试播放的wav文件:

  • Chunksize: 16 块大小:16
  • Format: 1 格式:1
  • Channel: 1 频道:1
  • SampleRate: 48000 SampleRate:48000
  • ByteRate: 96000 字节率:96000
  • BlockAlign: 2 BlockAlign:2
  • BitPerSample: 16 BitPerSample:16
  • Size of raw samples total: 2217044 bytes 原始样本总数:2217044字节

For some reason it works when I pass input parameters to the openStream() 由于某些原因,当我将输入参数传递给openStream()时,它可以工作

    RtAudio::StreamParameters oParameters, iParameters;
    oParameters.deviceId = rt.getDefaultOutputDevice();
    oParameters.firstChannel = 0;
    //oParameters.nChannels = mAudio.channels;
    oParameters.nChannels = mAudio.channels;

    iParameters.deviceId = rt.getDefaultInputDevice();
    iParameters.nChannels = 1;

    unsigned int sampleRate = mAudio.sampleRate;

    // Use a buffer of 512, we need to feed callback with 512 bytes everytime!
    unsigned int nBufferFrames = 512;

    RtAudio::StreamOptions options;
    options.flags = RTAUDIO_SCHEDULE_REALTIME;
    options.flags = RTAUDIO_NONINTERLEAVED;

    //&parameters, NULL, RTAUDIO_FLOAT64,sampleRate, &bufferFrames, &mCallback, (void *)&rawData

    try {
        rt.openStream(&oParameters, &iParameters, RTAUDIO_SINT16, sampleRate, &nBufferFrames, &mCallback, (void*) &mAudio);
        rt.startStream();
    }
    catch (RtAudioError& e) {
        std::cout << e.getMessage() << std::endl;
        return false;
    }
    return true;

It was so random when I was trying to playback my mic. 当我尝试播放麦克风时,声音是如此随机。 I left input parameters and my wav file was suddenly playing. 我离开了输入参数,我的wav文件突然播放了。 Is this is a bug? 这是一个错误吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM