0

I am working on an application that will provide audio input to some device. The device expects the audio input to be provided in the form of raw audio data stream (16 bit, 48kHz). So, irrespective of the format of audio data in the wave file (8-bit, 16-bit, 24-bit, 32-bit etc.), I want to extract raw audio data from the WAV file. I planned to use libsndFile library for this purpose. I modified the C++ sample code of libsndfile as shown below:

#include "stdafx.h"
#include <sndfile.hh>

static void create_file (const char * fname, int format, const short* buffer,const   unsigned int& len)
{   
    // file ;
    int channels = 1 ;  //A Mono wave file.
    int srate = 48000 ;

    printf ("Creating file named '%s'\n", fname) ;

    SndfileHandle file = SndfileHandle (fname, SFM_WRITE, format, channels, srate) ;

    int x = file.write (buffer, len) ;
}

static void read_file (const char * fname)
{   
    SndfileHandle       file ;

    file = SndfileHandle (fname) ; 

    const unsigned int uiBuffLen = file.channels() * file.frames();
    short* data = new short [uiBuffLen] ;
    memset(data,0x00,uiBuffLen);

    int x = file.command(SFC_SET_SCALE_FLOAT_INT_READ, (void*)data, uiBuffLen);
    file.read (data, uiBuffLen) ;   //Read the audio data in the form of 16 bit short integer

    //Now create a new wave file with audio data in the form of 16 bit short integers
    create_file ("ConvertedFile.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16,data, (const unsigned int&)uiBuffLen) ;

    //Now fill a buffer containing audio data and dump it into a file so that the same can be fed to a device expecting the raw audio data

    unsigned char* bytBuffer = new unsigned char[uiBuffLen*2];
    memset(bytBuffer, 0x00, uiBuffLen*2);
    file.readRaw(bytBuffer, uiBuffLen*2);

    FILE * pFile;
    pFile = fopen ("RawAudio.dat","w");
    if (pFile!=NULL)
    {
        fwrite(bytBuffer, 1, uiBuffLen*2, pFile);
        fclose (pFile);
    }       

    delete [] data;
    delete [] bytBuffer;
    }

int _tmain(int argc, _TCHAR* argv[])
{
    //The sample file is a Mono file containing audio data in float format.
    const char * fname = "MonoWavFile.wav" ;

    read_file (fname) ;

    return 0;
}

Well, the above code might look horrible, but I am just looking for the idea at the moment. I use a file "MonoWaveFile.wav" which is a mono wave file and has audio data in the form of 32 bit float values. I create a new file "ConvertedFile.wav" using the libsndfile library. This file has audio data in 16-bit PCM format. I play this file in a media player and I see that the conversion has been done properly.

Then I create another file "RawAudio.dat" to save only the audio data, which I can use to feed the audio input to the device. The file is created and when I send it to the device, the audio is not proper at all. This indicates that I am doing somthing horribly wrong. Can any one let me know what wrong I am doing? I have never worked on anything like this before, so I will appreciate if I get any sort of help.

user2837808
  • 1
  • 1
  • 2
  • I have shared the Python and C++ code on this link : http://stackoverflow.com/questions/43425176/plot-fft-of-wav-file-using-c/43447735#43447735 – Shivansh Jagga Apr 19 '17 at 15:28
  • See the simple 4-line example [here](https://github.com/erikd/libsndfile/blob/master/examples/sndfilehandle.cc#L52). – bcattle Jun 12 '17 at 06:41

1 Answers1

1

I used sf_open_virtual. I made another buffer which I have filled using sf_open_virtual. Then I used this "another buffer" to feed RTP packets. So I guess this is what you need.

I have problems making it the other directions from RTP packet to file.

//============================================================================
// Name        : libsndfile_demo.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <string.h>
#include "sndfile.h"
#include <assert.h>
#include <unistd.h>


using namespace std;

typedef struct
{   sf_count_t offset, length ;
    unsigned char data [160] ;
} VIO_DATA ;


FILE *checker;
const void* old_ptr = NULL;

static sf_count_t vfget_filelen (void *user_data)
{
    VIO_DATA *vf = (VIO_DATA *) user_data ;

    return vf->length ;
} /* vfget_filelen */

static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
{
    VIO_DATA *vf = (VIO_DATA *) user_data ;

    switch (whence)
    {   case SEEK_SET :
            vf->offset = offset ;
            break ;

        case SEEK_CUR :
            vf->offset = vf->offset + offset ;
            break ;

        case SEEK_END :
            vf->offset = vf->length + offset ;
            break ;
        default :
            break ;
        } ;

    return vf->offset ;
} /* vfseek */

static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
{
    VIO_DATA *vf = (VIO_DATA *) user_data ;

    /*
    **  This will brack badly for files over 2Gig in length, but
    **  is sufficient for testing.
    */
    if (vf->offset + count > vf->length)
        count = vf->length - vf->offset ;

    memcpy (ptr, vf->data + vf->offset, count) ;
    vf->offset += count ;

    return count ;
} /* vfread */

static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
{
    static int skip = 0;

    //TODO: Why this is working ?!?!?!
    if (skip < 1)
    {
        skip++;
        return count;
    }

    //SendTo RTP packetizer instead of writing to file
    fwrite(ptr, count, 1, checker);

    return count ;
} /* vfwrite */

static sf_count_t vftell (void *user_data)
{
    VIO_DATA *vf = (VIO_DATA *) user_data ;

    return vf->offset ;
} /* vftell */


int main()
{
    SF_INFO writing_sfinfo;
    writing_sfinfo.channels = 1;
    writing_sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_GSM610;
    writing_sfinfo.samplerate = 8000;
    assert(true == sf_format_check(&writing_sfinfo));

    SF_INFO reading_sfinfo;
    memset(&reading_sfinfo, 0, sizeof(reading_sfinfo));

    SNDFILE *input = sf_open("/home/georgi/Downloads/thank_you_60.PCMA", SFM_READ, &reading_sfinfo);
    checker = fopen("/home/georgi/Downloads/checker.wav", "w+");

    short file_data[reading_sfinfo.channels * 160];
    int read_frames = 0;

    SF_VIRTUAL_IO vio ;

    // Set up pointers to the locally defined functions.
    vio.get_filelen = vfget_filelen ;
    vio.seek = vfseek ;
    vio.read = vfread ;
    vio.write = vfwrite ;
    vio.tell = vftell ;

    VIO_DATA vio_data ;
    // Set virtual file offset and length to zero.
    vio_data.offset = 0 ;
    vio_data.length = 0 ;


    SNDFILE *virt_file = sf_open_virtual (&vio, SFM_WRITE, &writing_sfinfo, &vio_data);

    int old_length = 0;
    while ((read_frames = sf_readf_short(input, file_data, 160)))
    {
        sf_writef_short(virt_file, file_data, read_frames);
    }

    sf_close(virt_file);
    sf_close(input);
    fclose(checker);

    return 0;
}
Honza Zidek
  • 9,204
  • 4
  • 72
  • 118
Georgi
  • 19
  • 3