2015-01-30 5 views
2

오디오 신호 처리와 관련해서는 새로운 소식입니다.실시간으로 AUDIO 데이터를 WAV로 변환/변환

현재 마이크/재생 트랙에서 오디오 데이터를 전송하는 장치를 내 PC에 연결했습니다. 이미 Steinberg ASIO SDK 2.3을 사용하여 호스트 응용 프로그램을 만들고 장치에 연결하고 반복되는 콜백에서 원시 데이터를 반환합니다. 신호는 24 비트이며 원하는대로 주파수를 선택할 수 있습니다. 44100 Hz, 2 채널, 단일 채널을 예로 들어 보겠습니다. 나는이 신호를 또한 < -1.0, 1.0> 2로 변환했다. 왜냐하면 나는 그것에 신호 처리를하고 있기 때문이다.

지금 내가하고 싶은 것은 내 호스트에 녹음 기능을 추가하는 것입니다. 예를 들어 버튼을 클릭 할 때 들어오는 데이터는 WAV 파일로 계속 변환되고 다른 버튼을 클릭하면 멈추고 저장됩니다.

WAV 파일, 파일 형식, 비트 스트림 형식 (RIFF)에 대해 이미 읽었으며 WAV 파일의 모양이 어떻게되어 있는지 전반적인 아이디어가 있습니다. 또한 많은 포럼 스레드, stackoverflow 스레드 또는 코드 프로젝트 게시물을 확인하고 주제와 관련된 뭔가를 찾았지 만 실시간으로 진행중인 녹음을 어떻게 할 수 있는지 알 수 없습니다. 내가 찾은 많은 코드는 데이터 배열을 수정 한 후 WAV로 변환하는 것에 관한 것입니다. 나는 계속 진행되도록 변환을하고 WAV 파일을 추가/확장 할 때까지 계속 말하고 싶습니다.

예를 들어 어떻게 든 수정할 수 있습니까?

#include <fstream> 

template <typename T> 
void write(std::ofstream& stream, const T& t) { 
    stream.write((const char*)&t, sizeof(T)); 
} 

template <typename T> 
void writeFormat(std::ofstream& stream) { 
    write<short>(stream, 1); 
} 

template <> 
void writeFormat<float>(std::ofstream& stream) { 
    write<short>(stream, 3); 
} 

template <typename SampleType> 
void writeWAVData(
    char const* outFile, 
    SampleType* buf, 
    size_t bufSize, 
    int sampleRate, 
    short channels) 
{ 
    std::ofstream stream(outFile, std::ios::binary); 
    stream.write("RIFF", 4); 
    write<int>(stream, 36 + bufSize); 
    stream.write("WAVE", 4); 
    stream.write("fmt ", 4); 
    write<int>(stream, 16); 
    writeFormat<SampleType>(stream);        // Format 
    write<short>(stream, channels);         // Channels 
    write<int>(stream, sampleRate);         // Sample Rate 
    write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate 
    write<short>(stream, channels * sizeof(SampleType));   // Frame size 
    write<short>(stream, 8 * sizeof(SampleType));     // Bits per sample 
    stream.write("data", 4); 
    stream.write((const char*)&bufSize, 4); 
    stream.write((const char*)buf, bufSize); 
} 

그리고 어떻게 든 콜백에서

:

writeWAVData("mySound.wav", mySampleBuffer, mySampleBufferSize, 44100, 1); 

내가 도움의 힌트/링크/제안/양식에 대한 감사드립니다.

답변

3

사용 사례와 온라인에서 보았던 코드의 차이점은 사용 사례에서는 파일이 얼마나 오래 끝날지 미리 알지 못하기 때문입니다. 사용자가 정지 버튼을 누를 때.

이 문제를 처리하는 방법은 평소와 같이 WAV 헤더를 작성하는 것부터 시작하지만 파일 크기 특정 필드 (예 : "RIFF"뒤에있는 필드)에 대해 작성한 값은 걱정하지 마십시오. "데이터"다음의 필드). 이제는 해당 필드를 0으로 설정할 수 있습니다.

그런 다음 오디오 샘플을 수신 할 때이를 파일 끝에 붙여 넣습니다.

마지막으로 사용자가 멈추고 파일을 닫으려고하면 다시 돌아가서이 두 헤더 필드를 올바른 값으로 덮어 써야합니다. 이 시점에서 파일에 기록한 오디오 데이터의 바이트 수를 알 수 있으므로이 작업을 수행 할 수 있습니다. 일단 그 파일을 잘 작성하고 사용할 수 있어야합니다. 예 : ofstream::seekp(fieldOffset, ios_base::beg)을 사용하여 수정해야하는 필드의 파일 상단에서 적절한 오프셋을 찾습니다.

+0

매우 유익한 답변이었습니다. 정말 고마워요. 그래서 내가 이해할 수있는 파일을 추가하고 끝에 데이터를 작성해야합니다 - std :: ofstream stream (outFile, std :: ios :: binary :: append | std :: ate); 또한 RIFF 후 필드에 쓰기 (스트림, 0); 및 하나의 필드에 후 데이터 stream.write ((const char *) & bufSize, 0); 매개 변수 "mySampleBuffer"의 writeWAVData에서 샘플로 채워진 rawData (?)의 샘플을 버퍼에 삽입하고 변환 한 다음 WAV에 추가합니다. 그리고 멈출 때까지 계속 해. 정지 버튼에서 RIFF 및 DATA 뒤에 헤더를 찾고 필드를 덮어 써야합니까? – F1sher

+0

std :: ofstream stream (outFile, std :: ios :: binary | ios :: app | ios :: ate) : P 나는 전에 무언가를 썼다.내가 아직 작업하고 있지만 무언가가 녹화되고 WAV의 크기가 좋아지고있는 것 같아도 이제 헤더를 액세스하고 내부를보아야합니다. – F1sher