Two problems when writing to .WAV - C ++

I am currently writing a procedural music engine with openFrameworks in C ++. I can generate a song and play it from a normalized (between -1 and 1) floating-point buffer perfectly, however I have a couple of problems when I try to write the same buffer with floats to a 32-bit .WAV file.

  • When I play a file in the Finder preview (I'm on OSX 10.9.2), playing the entire length of the song is extremely cropped and distorted. It seems to be able to read the format, although it displays the correct file length, transfer rate, and http: //i.stack fetch speed . imgur.com/fz2w8.png . Oddly enough, when I drag the same file into Logic Pro X, it reads well, converts and plays without distortion. It also generates a waveform display, where I can see that the waveform for the two channels (stereo file) is fully normalized (for the first half at least ... see the next issue).

  • Despite the fact that Logic Pro X is able to read a file much more successfully than previewing Finder, there is a significant jump in amplitude exactly halfway through the song, and the waveform begins to be cut off (although nowhere is much the same as when playing Finder). This happens with every song generated (they are structurally, rhythmically and instrumentally different each time) that I tried to write in .WAV. Here you can see an example http://i.stack.imgur.com/59y5w.jpg .

Below is the code that I use to write to the .WAV file:

template <typename T>
void write(std::ofstream& stream, const T& t) {
    stream.write((const char*)&t, sizeof(T));
}

template <typename SampleType>
void writeWAVData(const char* outFile, SampleType* buf, size_t bufSize, int sampleRate, short channels)
{
    std::ofstream stream(outFile, std::ios::binary);                // Open file stream at "outFile" location

    /* Header */
    stream.write("RIFF", 4);                                        // sGroupID (RIFF = Resource Interchange File Format)
    write<int>(stream, 36 + bufSize);                               // dwFileLength
    stream.write("WAVE", 4);                                        // sRiffType

    /* Format Chunk */
    stream.write("fmt ", 4);                                        // sGroupID (fmt = format)
    write<int>(stream, 16);                                         // Chunk size (of Format Chunk)
    write<short>(stream, 1);                                        // Format (1 = PCM)
    write<short>(stream, channels);                                 // Channels
    write<int>(stream, sampleRate);                                 // Sample Rate
    write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate
    write<short>(stream, channels * sizeof(SampleType));            // Frame size aka Block align
    write<short>(stream, 8 * sizeof(SampleType));                   // Bits per sample

    /* Data Chunk */
    stream.write("data", 4);                                        // sGroupID (data)
    stream.write((const char*)&bufSize, 4);                         // Chunk size (of Data, and thus of bufferSize)
    stream.write((const char*)buf, bufSize);                        // The samples DATA!!!
}

I call the writeWAVData function with the following line:

writeWAVData(path.c_str(), &buffer[0], sampleDuration * NUM_OF_CHANNELS * sizeof(buffer[0]), sampleRate, NUM_OF_CHANNELS);

Where:

  • path is a string from the file path.
  • buffer float, ( , cout , , -1.0f 1.0f - ).
  • sampleRate - int.
  • sampleDuration - int.
  • NUM_OF_CHANNELS - , int (2 ).

, , !

: , "Format Chunk" 1, PCM. 3 ( FLOAT), .wav . qaru.site/questions/1530431/....

+4
1

, , . , :

buffer - , ( , cout , , -1.0f 1.0f - ).

float, WAV/PCM , 8 16 . 32 float ints.

3 :

  • char[] short[]
  • float[], char[] short[]
  • : format-tag 3/FLOAT 1/PCM, . .
+2

Source: https://habr.com/ru/post/1530431/


All Articles