2013-10-11 10 views
0

일부 장치에 오디오 입력을 제공하는 응용 프로그램을 작성 중입니다. 이 장치는 오디오 입력이 원시 오디오 데이터 스트림 (16 비트, 48kHz)의 형태로 제공 될 것으로 기대합니다. 따라서 웨이브 파일 (8 비트, 16 비트, 24 비트, 32 비트 등)의 오디오 데이터 형식에 관계없이 WAV 파일에서 원시 오디오 데이터를 추출하려고합니다. 이 목적으로 libsndFile 라이브러리를 사용할 계획이었습니다. C++에서 libsndfile을 사용하여 WAV 파일에서 원시 오디오 데이터 추출

#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; 
} 

음, 위의 코드는 끔찍한 보일 수 있습니다,하지만 난 그냥 순간에 아이디어를 찾고 있어요 : 아래 그림과 같이 내가 libsndfile의 C++ 샘플 코드를 수정했습니다. 모노 웨이브 파일 인 "MonoWaveFile.wav"파일을 사용하고 32 비트 부동 소수점 값 형식의 오디오 데이터를 가지고 있습니다. libsndfile 라이브러리를 사용하여 "ConvertedFile.wav"라는 새 파일을 만듭니다. 이 파일의 오디오 데이터는 16 비트 PCM 형식입니다. 미디어 플레이어에서이 파일을 재생하고 변환이 제대로 수행되었는지 확인합니다.

그런 다음 오디오 입력을 장치에 공급하는 데 사용할 수있는 오디오 데이터 만 저장하는 "RawAudio.dat"파일을 만듭니다. 파일이 생성되고 장치로 보낼 때 오디오가 전혀 적합하지 않습니다. 이것은 내가 끔찍한 잘못을 저지르고 있음을 나타냅니다. 아무도 내가 뭘 잘못하고 있는지 알려 줄 수 있습니까? 전에 이런 식으로 일한 적은 없기 때문에 도움이된다면 고맙겠습니다.

+0

내가이 링크에 파이썬과 C++ 코드를 공유 : http://stackoverflow.com/questions/43425176/plot-fft-of-wav-file-using-c/43447735#43447735 –

+0

을 참조하십시오 간단한 4 줄 예제 [here] (https://github.com/erikd/libsndfile/blob/master/examples/sndfilehandle.cc#L52). – bcattle

답변

0

나는 sf_open_virtual을 사용했습니다. sf_open_virtual을 사용하여 채운 다른 버퍼를 만들었습니다. 그런 다음이 "다른 버퍼"를 사용하여 RTP 패킷을 제공했습니다. 이것이 내가 필요한 것 같아.

RTP 패킷에서 파일로의 다른 방향을 만드는 데 문제가 있습니다.

//============================================================================ 
// 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; 
} 
관련 문제