0

I am working on a project where I need to take input from a microphone in c++, and create a wav file that stores the recorded microphone. Right now, I made a simple function that just reads from the microphone, and dumps it into a bin file. I can open it in audacity and hear what I said, but I wish to convert it to sound through my program in lets say a function. Is there anyway I can create a function to convert a binary file into a wav format? It doesn't have to be wav, it can be any popular sound format such as mp3. This is my function for getting the sound --

#pragma comment(lib,"winmm.lib")

#include <Windows.h>
#include <mmsystem.h>
#include <fstream>
#include <iostream>

void AudioReader::AudioReader::AutioToBinary() {
    WAVEFORMATEX wfx = {};
    wfx.wFormatTag = WAVE_FORMAT_PCM;       // PCM is standard
    wfx.nChannels = 2;                      // 2 channels = stereo sound
    wfx.nSamplesPerSec = 44100;             // Samplerate.  44100 Hz
    wfx.wBitsPerSample = 32;                // 32 bit samples

    wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    HWAVEIN wi;
    waveInOpen(
        &wi,         
        WAVE_MAPPER,    
        &wfx,          
        NULL, NULL,     
        CALLBACK_NULL | WAVE_FORMAT_DIRECT  
    );

    char buffers[2][44100 * 2 * 2 / 2];   
    WAVEHDR headers[2] = { {},{} };         
    for (int i = 0; i < 2; ++i){
        headers[i].lpData = buffers[i];
        headers[i].dwBufferLength = 44100 * 2 * 2 / 2;      

        waveInPrepareHeader(wi, &headers[i], sizeof(headers[i]));
        waveInAddBuffer(wi, &headers[i], sizeof(headers[i]));
    }

    
    std::ofstream outfile("Audio.bin", std::ios_base::out | std::ios_base::binary);

    std::cout << "Started recording! Press escape when you're ready to stop!\n";
    waveInStart(wi);
  
    while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000))  {
        for (auto& h : headers) {
            if (h.dwFlags & WHDR_DONE) {
               
                outfile.write(h.lpData, h.dwBufferLength); //dump audio binary to bin file

                h.dwFlags = 0;        
                h.dwBytesRecorded = 0; 

                waveInPrepareHeader(wi, &h, sizeof(h));
                waveInAddBuffer(wi, &h, sizeof(h));
            }
        }
    }
    waveInStop(wi);
    for (auto& h : headers){
        waveInUnprepareHeader(wi, &h, sizeof(h));
    }
    waveInClose(wi);
}

UPDATE: Hello again, I have done some more research and I have made my own headers. I have another question, how do I implement the headers into the wav file? I tried doing it in the traditional ofstream method, but that doesn't work at the moment. This is the function I made for it --

void AudioReader::AudioReader::BinaryToWav(wavehdr_tag& bin) {
    std::ofstream WavFile("Audio.wav", std::ios_base::binary);

    //FMT Sub-Chunk
    std::string SubChunk1ID = "fmt";
    int SubChunk1Size = 16;
    int AudioFormat = 1;
    int NumChannels = 2;
    int SampleRate = 44100;
    int BitsPerSample = 16;

    int ByteRate = SampleRate * NumChannels * BitsPerSample / 8;
    int BlockAlign = NumChannels * BitsPerSample / 8;

    //Data
    std::string SubChunk2ID = "data";
    int SubChunk2Size = 1 * NumChannels * BitsPerSample / 8;

    //RIFF
    std::string ChunkID = "RIFF";
    int ChunkSize = 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size);
    std::string Format = "WAVE";

    //dump params to file
    WavFile
        << ChunkID
        << ChunkSize 
        << Format 
        << SubChunk1ID 
        << SubChunk1Size 
        << AudioFormat 
        << NumChannels
        << SampleRate 
        << ByteRate 
        << BlockAlign 
        << BitsPerSample
        << SubChunk2ID
        << SubChunk2Size
        << bin.lpData << bin.dwBufferLength;
}
Comyar D
  • 172
  • 2
  • 9
  • Of course there's a way to" create a function to convert a binary file into a wav format". C++ can do anything. You just have to write the code to do it. The format of a `.wav` file is publicly available at www.google.com, simply write a C++ function that creates a file in that format. Mission accomplished. – Sam Varshavchik Oct 17 '20 at 23:02
  • Hey Sam, I should have been more clear. How do you do that? – Comyar D Oct 17 '20 at 23:13
  • You do it exactly the same way that you do anything else in C++: write the code to do it, compile it, and then test it. It just so happens that I have a custom hookup of an AM/FM radio with its audio out port hooked up to audio-in on my server, and a timed job that dumps raw audio from a radio station. When I wanted to convert that into a `.wav` file, I did exactly what I told you: look up the `.wav` format in Google, and implement a simple C++ function that prepended a `WAV` hdr to the raw file that my audio dump code captured, creating a `.wav` right off the bat. The End. – Sam Varshavchik Oct 17 '20 at 23:21
  • Hey sam, I found a site with the params I could enter : http://soundfile.sapp.org/doc/WaveFormat/. My question is, do I just decalre the values as variables, create an std::ofstream object. The put the params into the object? such as the binary data and other parameters listed into the website? – Comyar D Oct 18 '20 at 02:25
  • I think what @SamVarshavchik is obliquely trying to say is that you have to first attempt a solution before anyone can help. There isn't a right or wrong way to write a wave file, so long as you end up with wav file at the end. There aren't many immediate questions on SO about a [plain wav write](https://stackoverflow.com/search?q=%5Bc%2B%2B%5D%5Bwav%5Dwrite) there are [plenty on reading](https://stackoverflow.com/search?tab=votes&q=%5bwav%5d%5bc%2b%2b%5dread), of which this [SO Answer would be a good place to start](https://stackoverflow.com/a/13661263/8876321) – fdcpp Oct 18 '20 at 11:36
  • Reading / Writing `wav` files are very similar operations. I believe it was once a very common entry level exercise in University C / C++ courses. It would beneficial to approach this in a few different ways to help get to grips with C / C++ coding. – fdcpp Oct 18 '20 at 11:41
  • I have had an attempt at it so far. I have created the headers for it based on what i've read. My question is, how do I put the headers into the wav file? I tried putting it in through the ofstream method, and it hasn't exactly worked. How would I go about doing that? – Comyar D Oct 18 '20 at 18:00
  • This is a kicker and catches a few people out first time. `fmt ` includes a space at the end and is 4 bytes in length. This partially why approaching headers is best done with either `char` arrays. I would avoid `std::string` in this case – fdcpp Oct 18 '20 at 18:50
  • Hello, If I change that should my program be working correctly? Or is there anything else I need to add. – Comyar D Oct 19 '20 at 04:57

1 Answers1

0

Okay so I managed to find an article that walks you through how to do it. You need to have a bin value in order to do this, so you could use my code to get the bin from your microphone if you wish. Here is the article, and good luck! -- http://blog.acipo.com/generating-wave-files-in-c/. Also here is another site that did help me quite a lot on the understanding of why we need these headers -- http://soundfile.sapp.org/doc/WaveFormat/.

Comyar D
  • 172
  • 2
  • 9
  • For a good answer you should look to provide a self-contained solution. Think in terms of what you would have liked to have found when first asking your question. Be aware that links to external sites may rot. – fdcpp Oct 19 '20 at 12:50