Search code examples
caudiolibwebsockets

Save audio stream in file using C libwebsockets


I have a C server that uses libwebsockets and I want to save a received audio stream in a file on disk.

Here is my code snippet:

#define FILENAME        "/home/ubuntu/Desktop/file.wav"
FILE *received_file;

struct lws_context *Audiocontext;
static int callback_audio(
        struct lws *wsi,
        enum lws_callback_reasons reason,
        void *user, void *in, size_t len)
{
    switch (reason) {
        case LWS_CALLBACK_ESTABLISHED: 
        {
            printf("client is connected\n");
            received_file = fopen(FILENAME, "w+");
            if (received_file == NULL)
            {
                printf("Failed to open file\n");
                exit(EXIT_FAILURE);
            }
        }
        break;
        case LWS_CALLBACK_RECEIVE: {
            if(strcmp((char*)in,"EOS")==0)
            {
                printf("End of stream!\n");
                fclose(received_file);
            }
            else
            {
                fwrite(in, 1, len, received_file);
            }
        }
    }
}

I got the message "client is connected" and also the file, but the content isn't ok, I cannot play it. I think there is a problem regarding the way I save the stream on file using fwrite().

The client is sending audio chunks encoded as wav, 16Khz, mono. Here is a snippet from client (it's a javascript client, the full code is here:http://kaljurand.github.io/dictate.js/).

if (recorder) {
    recorder.stop();
    config.onEvent(MSG_STOP, 'Stopped recording');
    // Push the remaining audio to the server
    recorder.export16kMono(function(blob) {
        socketSend(blob);
        socketSend(TAG_END_OF_SENTENCE);
        recorder.clear();
        }, 'export16kMono');
    config.onEndOfSpeech();
} else {
    config.onError(ERR_AUDIO, "Recorder undefined");
}

The client is working well, I use it for exactly the same task, but using a Java server. I would appreciate if someone could indicate me how to save these audio chunks in a valid file.


Solution

  • I think that you do not write header in your wav file. To do so,

    • you can write some function to do so see specification here
    • or you can use a dedicaded library, like libsndfile, which is not so complicated to use:

      // instead of fopen, write something like
      SF_INFO info;
      SNDFILE * sf;
      
      info.samplerate = sample_rate;
      info.channels = 1;
      info.sections = 1;
      info.seekable = 0;
      info.frames = 0;
      info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
      
      sf = sf_open(filename, SFM_WRITE, &info);
      

      // instead of fwrite, something like
      sf_write_short(sf, in, len / sizeof(short));
      

      // and instead of fclose
      sf_close(sf);