2013-04-18 1 views
10

저는 현재 매우 중요한 학교 프로젝트를 진행하고 있습니다. C/C++에서 WAVE 파일의 정보를 추출하고이 정보를 사용하여 음성 신호의 LPC를 얻어야합니다. 그러나이를 수행하기 위해 제로 크로싱과 에너지 분석을 수행하는 등 신호 처리를 사전 처리해야합니다. 즉, 나는 기호와 진정한 가치가 필요하다는 것을 의미합니다. 문제는 유용한 정보와 올바른 형식을 얻는 방법을 모른다는 것입니다. 이미 파일의 모든 단일 필드를 읽었지만 올바르게 처리하고 있는지 확신 할 수 없습니다. 제안, 제발? C/C++에서 WAV 파일 데이터 읽기 및 처리

이 제가

순간 파일을 판독하는 방식이다

readI = FREAD (& BPS, 1, 2, 오디오); printf ("샘플 당 비트 수 = % d \ n", bps);

미리 감사드립니다.

+3

http://www.mega-nerd.com/libsndfile/ http://ccrma.stanford.edu/software/snd/sndlib/는 WAV로 작업하는 데 도움이되는 두 개의 라이브러리입니다 – Patashu

답변

15

첫 번째 권장 사항은 도움이되는 일종의 라이브러리를 사용하는 것입니다. 대부분의 사운드 솔루션은 잔인한 것처럼 보이므로 간단한 라이브러리 (질문에 대한 답변에서 추천 한 것과 같은 libsndfile)가이 트릭을 수행해야합니다.

WAV 파일을 읽는 방법을 알고 싶다면 (학교에서 다른 일반 사람과 같이 라이브러리를 사용하는 데 학교가 도움이 될 수 있기 때문에) 직접 쓸 수 있도록 WAV 파일을 읽는 방법을 알고 싶다면 빠른 Google 검색을 통해 필요한 모든 정보 plus some people who have already wrote many tutorials on reading the .wav format.

아직 이해가되지 않는다면, 데이터 청크에 도착할 때까지 헤더와 WAV/RIFF 데이터 파일의 다른 모든 청크를 읽는 코드를 작성하십시오. 그것은 exclusively off the WAV Format Specification을 기반으로합니다. 실제 사운드 데이터를 추출하는 것은 그리 어렵지 않습니다. 원시를 읽거나 원시를 사용하거나 내부적으로 (32 비트 PCM 압축되지 않은 데이터 등) 더 편한 형식으로 변환 할 수 있습니다.

아래 코드를 살펴볼 때 fread은 표시된 값의 정수 값 및 바이트 크기를 호출하는 것으로 reader.Read...(...)을 대체하십시오. WavChunks는 WAV 파일 청크의 내부 ID의 리틀 엔디안 값입니다 열거이며, format 변수는 WAV 파일 형식에 포함 할 수있는 WAV 형식 유형의 종류 중 하나입니다

enum class WavChunks { 
    RiffHeader = 0x46464952, 
    WavRiff = 0x54651475, 
    Format = 0x020746d66, 
    LabeledText = 0x478747C6, 
    Instrumentation = 0x478747C6, 
    Sample = 0x6C706D73, 
    Fact = 0x47361666, 
    Data = 0x61746164, 
    Junk = 0x4b4e554a, 
}; 

enum class WavFormat { 
    PulseCodeModulation = 0x01, 
    IEEEFloatingPoint = 0x03, 
    ALaw = 0x06, 
    MuLaw = 0x07, 
    IMAADPCM = 0x11, 
    YamahaITUG723ADPCM = 0x16, 
    GSM610 = 0x31, 
    ITUG721ADPCM = 0x40, 
    MPEG = 0x50, 
    Extensible = 0xFFFE 
}; 

int32 chunkid = 0; 
bool datachunk = false; 
while (!datachunk) { 
    chunkid = reader.ReadInt32(); 
    switch ((WavChunks)chunkid) { 
    case WavChunks::Format: 
     formatsize = reader.ReadInt32(); 
     format = (WavFormat)reader.ReadInt16(); 
     channels = (Channels)reader.ReadInt16(); 
     channelcount = (int)channels; 
     samplerate = reader.ReadInt32(); 
     bitspersecond = reader.ReadInt32(); 
     formatblockalign = reader.ReadInt16(); 
     bitdepth = reader.ReadInt16(); 
     if (formatsize == 18) { 
      int32 extradata = reader.ReadInt16(); 
      reader.Seek(extradata, SeekOrigin::Current); 
     } 
     break; 
    case WavChunks::RiffHeader: 
     headerid = chunkid; 
     memsize = reader.ReadInt32(); 
     riffstyle = reader.ReadInt32(); 
     break; 
    case WavChunks::Data: 
     datachunk = true; 
     datasize = reader.ReadInt32(); 
     break; 
    default: 
     int32 skipsize = reader.ReadInt32(); 
     reader.Seek(skipsize, SeekOrigin::Current); 
     break; 
    } 
} 
+1

왜 RIFF가 16 진수로 쓰여졌습니까? 리틀/빅 엔디안에 대해 알고 있지만, 필자가 사용한 16 진수 편집자는 FFIR 대신 RIFF로 표시합니다. 장면 뒤에서 이상한 변환을하고 있습니까? 아니면 계속 진행되고 있습니까? – MarcusJ

+0

@ MarcusJ가 RIFF를 읽어야한다고 생각합니다. 여기에 웨이브 형식 http://soundfile.sapp.org/doc/WaveFormat/에 대한 설명이 있습니다. 그래서 RiffHeader = 0x52494646이어야한다고 생각합니다. 이엔 필드 – alexm