波形文件导出已损坏

Posted

技术标签:

【中文标题】波形文件导出已损坏【英文标题】:wave file export is corrupted 【发布时间】:2014-08-01 17:57:24 【问题描述】:

我编写了两个函数,它们应该将音频浮点缓冲区导出到 .wav 文件中,但播放导出的文件时遇到问题。 Audacity 以应有的方式播放(听起来与我的应用程序中的完全一样),但是,Ableton(DAW 软件)似乎误解了 wav 的某些部分,因此听起来确实失真。 (像失真效果)

我猜ableton 以某种方式假设了错误的样本深度(更小),因此实际样本超出了限制。

我有两个函数,一个从两个浮点缓冲区创建一个int32_t 缓冲区(将左右混合到一个缓冲区中),另一个函数写入 .wav 文件,包括格式块等。我猜某处有问题。

类成员/结构

// static I use in the export function
static const int FORMAT_PCM = 1;
static const int CHANNEL_COUNT = 2;    // fix stereo
static const int BYTES_PER_SAMPLE = 4; // fix bytes per sample, 32bit audio

// a function I found in the internet, helps writting the bytes to the file
template <typename T>
static void write(std::ofstream& stream, const T& t) 
    stream.write((const char*)&t, sizeof(T));
;

// used "structure" to store the buffer
class StereoAudioBuffer 
public:
    StereoAudioBuffer(int length) : sizeInSamples(2*length)
        samples = new int32_t[2*length];
    ;
    ~StereoAudioBuffer() delete samples;;

    int32_t *samples;
    const int sizeInSamples;
;

转换函数

StereoAudioBuffer* WaveExport::convertTo32BitStereo(
        float *leftSamples, 
        float*rightSamples, 
        int length) 

    StereoAudioBuffer *buffer = new StereoAudioBuffer(length);
    float max = 0;

    // find max sample 
    for(int i = 0; i < length; i++) 
        if(abs(leftSamples[i]) > max) 
            max = abs(leftSamples[i]);
        
        if(abs(rightSamples[i]) > max) 
            max = abs(rightSamples[i]);
        
    



    // normalise and scale to size(int32_t)

    float factor = 2147483000.0f / max;

    for(int i = 0; i < length; i++) 
        buffer->samples[2*i] = leftSamples[i] * factor ;
        buffer->samples[2*i+1] = rightSamples[i] * factor;
    
    return buffer;

导出功能(部分代码来源于网络,可惜找不到源代码了

void WaveExport::writeStereoWave(
        const char *path, 
        StereoAudioBuffer* buffer, 
        int sampleRate) 

    std::ofstream stream(path, std::ios::binary);

    // RIFF
    stream.write("RIFF", 4);

    // FILE SIZE
    write<int>(stream, 36 + buffer->sizeInSamples * BYTES_PER_SAMPLE); // 32 bits -> 4 bytes

    // WAVE
    stream.write("WAVE", 4);

    // FORMAT CHUNK
    stream.write("fmt ", 4);

    write<int>(stream, 16);

    write<short>(stream, FORMAT_PCM);                                       // Format
    write<short>(stream, CHANNEL_COUNT);                                    // Channels
    write<int>(stream, sampleRate);                                         // Sample Rate
    write<int>(stream, sampleRate * CHANNEL_COUNT * BYTES_PER_SAMPLE);      // Byterate
    write<short>(stream, CHANNEL_COUNT * BYTES_PER_SAMPLE);                 // Frame size
    write<short>(stream, 8 * BYTES_PER_SAMPLE);                             // Bits per sample

    int dataChunkSize = buffer->sizeInSamples * BYTES_PER_SAMPLE;
    // SAMPLES
    stream.write("data", 4);
    stream.write((const char*)&dataChunkSize, 4);
    stream.write((const char*)buffer->samples, BYTES_PER_SAMPLE*buffer->sizeInSamples);

有谁知道如何编写 .wav 文件,也许可以告诉我我做错了什么或错过了什么? 谢谢!

【问题讨论】:

【参考方案1】:

没有问题。我使用了应用程序不支持的 32 位 .wav,用于播放。

我将导出函数更改为使用 int16_t,16 位深度,它工作正常。

【讨论】:

以上是关于波形文件导出已损坏的主要内容,如果未能解决你的问题,请参考以下文章

Webapi 导出到 excel 下载的损坏文件

ssrs报告导出到excel - 损坏的超链接

FPGA-vivado仿真导出波形文件

AU如何导出音频?

MySQL导出数据时提示文件损坏

excel文件格式和扩展名不匹配.文件可能已损坏怎么办