Wave Format - отрицательный размер данных - PullRequest
0 голосов
/ 24 сентября 2018

Я работаю с файлами Wave.Я читаю все данные, но в некоторых файлах размер данных (указанное количество байтов для чтения) отрицателен, что нарушает механизм чтения.Являются ли волновые файлы постоянными с точки зрения смещения байтов?Смещение по х всегда одно и то же значение?

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Являются ли волновые файлы постоянными с точки зрения смещения байтов?Является ли смещение x всегда одним и тем же значением?

Нет, по крайней мере, секция данных не всегда находится с одинаковым смещением.Некоторые простые программы предполагают, что звуковые сэмплы начинаются с фиксированного смещения (44), но это не всегда так.Единственный способ надежного чтения волнового файла - это поиск раздела данных, и как только вы его найдете, поле размера данных будет со смещением +4 относительно раздела данных.

0 голосов
/ 30 декабря 2018

Если это поможет, это то, что я использую для декодирования / кодирования wav (я кодировал несколько лет назад):

//---------------------------------------------------------------------------
//--- RIFF WAVE format: 1.01 ------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _RIFF_h
#define _RIFF_h
//---------------------------------------------------------------------------
// 8bit PCM is unsigned
// 16bit PCM is signed 2'os complement little endian (big endian is RIFX)
//---------------------------------------------------------------------------
struct _wave_chunk
    {
    DWORD ids;
    DWORD len;
    _wave_chunk(){ ids='    '; len=0; }
    _wave_chunk(_wave_chunk& a){ *this=a; }; ~_wave_chunk(){}; _wave_chunk* operator = (const _wave_chunk *a) { *this=*a; return this; }; /*_wave_chunk* operator = (const _wave_chunk &a) { ...copy... return this; };*/
    };
struct _wave_hdr
    {
    DWORD ids;      // "RIFF"
    DWORD len;
    DWORD tps;      // "WAVE"
    _wave_hdr(){ ids='FFIR'; len=0; tps='EVAW'; }
    _wave_hdr(_wave_hdr& a){ *this=a; }; ~_wave_hdr(){}; _wave_hdr* operator = (const _wave_hdr *a) { *this=*a; return this; }; /*_wave_hdr* operator = (const _wave_hdr &a) { ...copy... return this; };*/
    };
struct _wave_fmt
    {
    DWORD ids;      // "fmt "
    DWORD len;      // 16,18,40
    WORD  format;   // 1 = PCM linear quantization
/*                      0x0001  WAVE_FORMAT_PCM PCM
                        0x0003  WAVE_FORMAT_IEEE_FLOAT  IEEE float
                        0x0006  WAVE_FORMAT_ALAW    8-bit ITU-T G.711 A-law
                        0x0007  WAVE_FORMAT_MULAW   8-bit ITU-T G.711 µ-law
                        0xFFFE  WAVE_FORMAT_EXTENSIBLE  Determined by SubFormat */
    WORD  chanels;
    DWORD samplerate;
    DWORD byterate;
    WORD  blockalign;
    WORD  bits;
    WORD  ext_len;  // extension length 0,22
    WORD  ext_validbits;
    DWORD ext_channelmask;
    BYTE  ext_subformat[16];
    _wave_fmt(){ ids=' tmf'; len=16; format=1; chanels=1; samplerate=44100; bits=8; ext_len=0; ext_validbits=0; ext_channelmask=0; for (int i=0;i<16;i++) ext_subformat[i]=0; compute(); }
    _wave_fmt(_wave_fmt& a){ *this=a; }; ~_wave_fmt(){}; _wave_fmt* operator = (const _wave_fmt *a) { *this=*a; return this; }; /*_wave_fmt* operator = (const _wave_fmt &a) { ...copy... return this; };*/
    void compute()
        {
        byterate=(chanels*samplerate*bits)/8;
        blockalign=(chanels*bits)/8;
        }
    };
struct _wave_dat
    {
    DWORD ids;      // "data"
    DWORD len;
    _wave_dat(){ ids='atad'; len=0; }
    _wave_dat(_wave_dat& a){ *this=a; }; ~_wave_dat(){}; _wave_dat* operator = (const _wave_dat *a) { *this=*a; return this; }; /*_wave_dat* operator = (const _wave_dat &a) { ...copy... return this; };*/
    };
//---------------------------------------------------------------------------
class wave
    {
public:
    AnsiString name;
    int hnd;
    bool readonly;
    _wave_hdr hdr;
    _wave_fmt fmt;
    _wave_dat dat;

    wave();
    ~wave();
    void create(AnsiString _name);
    void write(BYTE *data,DWORD size);

    bool open(AnsiString _name);
    DWORD read(BYTE *data,DWORD size);
    void close();
    };
//---------------------------------------------------------------------------
wave::wave()
    {
    name=0;
    hnd=-1;
    readonly=true;
    }
//---------------------------------------------------------------------------
wave::~wave()
    {
    close();
    }
//---------------------------------------------------------------------------
void wave::create(AnsiString _name)
    {
    close();
    readonly=true;
//  hdr=_wave_hdr();
//  fmt=_wave_fmt();
//  dat=_wave_dat();
    hdr.len=sizeof(hdr)-8;
    dat.len=0;
    fmt.compute();
    name=_name;
    hnd=FileCreate(name);
    if (hnd<0) return;
    FileWrite(hnd,&hdr,sizeof(hdr));
    FileWrite(hnd,&fmt,fmt.len+8);
    FileWrite(hnd,&dat,sizeof(dat));
    readonly=false;
    }
//---------------------------------------------------------------------------
bool wave::open(AnsiString _name)
    {
    close();
    readonly=true;
    name=_name;
    hnd=FileOpen(name,fmOpenRead);
    if (hnd<0) return false;
    if (FileRead(hnd,&hdr,sizeof(hdr))<sizeof(hdr)){ close(); return false; }
    if (hdr.ids!='FFIR') return false;
    if (hdr.tps!='EVAW') return false;
    _wave_chunk chk;
    DWORD sz=sizeof(chk),l;
    for(;;)
        {
        if (FileRead(hnd,&chk,sz)<sz){ close(); return false; }
            if (chk.ids==' tmf')
            {
            fmt.ids=chk.ids;
            fmt.len=chk.len;
            if (FileRead(hnd,((BYTE*)&fmt)+sz,chk.len)<chk.len){ close(); return false; }
            }
        else if (chk.ids=='atad')
            {
            dat.ids=chk.ids;
            dat.len=chk.len;
            return true;
            }
        else FileSeek(hnd,int(chk.len),1);
        }
    }
//---------------------------------------------------------------------------
void wave::write(BYTE *data,DWORD size)
    {
    if (hnd<0) return;
    hdr.len+=size;
    dat.len+=size;
    if (!readonly) FileWrite(hnd,data,size);
    }
//---------------------------------------------------------------------------
DWORD wave::read(BYTE *data,DWORD size)
    {
    if (hnd<0) return 0;
    return FileRead(hnd,data,size);
    }
//---------------------------------------------------------------------------
void wave::close()
    {
    name="";
    if (hnd<0) return;
    FileSeek(hnd,0,0);
    if (!readonly) FileWrite(hnd,&hdr,sizeof(hdr));
    FileClose(hnd);
    hnd=-1;
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

это не поддерживает все форматы, но должно быть достаточно для сравнения и исправления вашего кодасоответственноизвлечь адрес ... Код основан на C ++ / VCL , поэтому вам нужно перенести двоичный доступ к файлу и тип данных AnsiString в вашу среду ...

Однако отрицательныйзначение предполагает, что вы снова используете целые числа со знаком (как и в другом вопросе ), поэтому используйте вместо этого тип данных без знака ... Смещения в RIFF Волновые файлы никогда не бывают отрицательными !!!

[Edit1] Я обновил код для новых форматов.

После добавления некоторых расширений (см. информация о формате от первого xbugКомментарий под OP) к формату Wave в формате fmt chunk теперь может иметь переменный размер.Кроме того, они добавили несколько других чанков (связанных со сжатием), поэтому для надежного чтения необходимо передать все чанки RIFF в зависимости от их размера, пока вы не достигнете чанка data, которому должны следовать ваши образцы данных...

Мой оригинальный код был для формата 1.0 (как уже упоминалось, он был закодирован несколько лет назад) и не загружал новые волновые файлы должным образом (спасибо dsp_user для его обнаружения).Я обновил его, добавив новое форматирование, чтобы его можно было безопасно использовать снова.

...