0

一部のデバイスにオーディオ入力を提供するアプリケーションに取り組んでいます。デバイスは、オーディオ入力が未加工のオーディオ データ ストリーム (16 ビット、48kHz) の形式で提供されることを想定しています。そのため、WAV ファイルのオーディオ データの形式 (8 ビット、16 ビット、24 ビット、32 ビットなど) に関係なく、WAV ファイルから生のオーディオ データを抽出したいと考えています。この目的のためにlibsndFileライブラリを使用する予定でした。以下に示すように、libsndfile の C++ サンプル コードを変更しました。

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

さて、上記のコードはひどいものに見えるかもしれませんが、私は今のところそのアイデアを探しています. モノウェーブファイルであり、32ビット浮動小数点値の形式のオーディオデータを持つファイル「MonoWaveFile.wav」を使用します。libsndfile ライブラリを使用して、新しいファイル「ConvertedFile.wav」を作成します。このファイルには、16 ビット PCM 形式の音声データが含まれています。このファイルをメディア プレーヤーで再生すると、変換が適切に行われていることがわかります。

次に、別のファイル "RawAudio.dat" を作成してオーディオ データのみを保存します。これを使用して、オーディオ入力をデバイスに送ります。ファイルが作成され、デバイスに送信すると、オーディオがまったく正しくありません。これは、私がひどく間違ったことをしていることを示しています。誰が私が何をしているのか教えてもらえますか? 私はこれまでにこのような作業をしたことがないので、何か助けがあれば幸いです。

4

1 に答える 1

1

使用し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;
}
于 2014-07-17T10:33:00.670 に答える