문제

NI 데이터 수집 모듈을 사용하여 48ksps로 '현장'에서 캡처한 몇 Gb의 샘플 데이터가 있습니다.이 데이터로 WAV 파일을 만들고 싶습니다.

저는 이전에 MATLAB을 사용하여 데이터를 로드하고 16비트 PCM 범위로 정규화한 다음 WAV 파일로 작성했습니다.그러나 MATLAB은 모든 작업을 '메모리 내'에서 수행하므로 파일 크기에 문제가 있습니다.

이상적으로는 C++ 또는 C(C#은 옵션)에서 이 작업을 수행하거나 기존 유틸리티가 있는 경우 해당 유틸리티를 사용합니다.간단한 방법이 있나요(예:기존 라이브러리) 원시 PCM 버퍼를 가져와 샘플 속도와 비트 심도를 지정하고 이를 WAV 파일로 패키징하려면 어떻게 해야 할까요?

대규모 데이터 세트를 처리하려면 전체 세트를 메모리로 읽는 것이 반드시 가능하지는 않기 때문에 데이터를 청크로 추가할 수 있어야 합니다.

나는 형식 사양을 사용하여 처음부터 이 작업을 수행할 수 있다는 것을 이해하지만 바퀴를 다시 발명하거나 도움이 될 수 있다면 버그를 수정하는 데 시간을 보내고 싶지 않습니다.

도움이 되었습니까?

해결책

나는 당신이 사용할 수 있다고 생각합니다 libsox 이것을 위해.

다른 팁

흥미롭게도, 나는 코드의 stackoverflow parse에서 버그를 발견했다. 그것은 아래에서 볼 수 있듯이 줄 끝에서 문자를 지원하지 않는다.

//stolen from OGG Vorbis pcm to wav conversion rountines, sorry
#define VERSIONSTRING "OggDec 1.0\n"

static int quiet = 0;
static int bits = 16;
static int endian = 0;
static int raw = 0;
static int sign = 1;
unsigned char headbuf[44];  /* The whole buffer */







#define WRITE_U32(buf, x) *(buf)     = (unsigned char)((x)&0xff);\
                          *((buf)+1) = (unsigned char)(((x)>>8)&0xff);\
                          *((buf)+2) = (unsigned char)(((x)>>16)&0xff);\
                          *((buf)+3) = (unsigned char)(((x)>>24)&0xff);

#define WRITE_U16(buf, x) *(buf)     = (unsigned char)((x)&0xff);\
                          *((buf)+1) = (unsigned char)(((x)>>8)&0xff);

/*
 * Some of this based on ao/src/ao_wav.c
 */
static int
write_prelim_header (FILE * out, int channels, int samplerate)
{

  int knownlength = 0;

  unsigned int size = 0x7fffffff;
  // int channels = 2;
  // int samplerate = 44100;//change this to 48000
  int bytespersec = channels * samplerate * bits / 8;
  int align = channels * bits / 8;
  int samplesize = bits;

  if (knownlength)
    size = (unsigned int) knownlength;

  memcpy (headbuf, "RIFF", 4);
  WRITE_U32 (headbuf + 4, size - 8);
  memcpy (headbuf + 8, "WAVE", 4);
  memcpy (headbuf + 12, "fmt ", 4);
  WRITE_U32 (headbuf + 16, 16);
  WRITE_U16 (headbuf + 20, 1);  /* format */
  WRITE_U16 (headbuf + 22, channels);
  WRITE_U32 (headbuf + 24, samplerate);
  WRITE_U32 (headbuf + 28, bytespersec);
  WRITE_U16 (headbuf + 32, align);
  WRITE_U16 (headbuf + 34, samplesize);
  memcpy (headbuf + 36, "data", 4);
  WRITE_U32 (headbuf + 40, size - 44);

  if (fwrite (headbuf, 1, 44, out) != 44)
    {
      printf ("ERROR: Failed to write wav header: %s\n", strerror (errno));
      return 1;
    }

  return 0;
}

static int
rewrite_header (FILE * out, unsigned int written)
{
  unsigned int length = written;

  length += 44;

  WRITE_U32 (headbuf + 4, length - 8);
  WRITE_U32 (headbuf + 40, length - 44);
  if (fseek (out, 0, SEEK_SET) != 0)
    {
      printf ("ERROR: Failed to seek on seekable file: %s\n",
          strerror (errno));
      return 1;
    }

  if (fwrite (headbuf, 1, 44, out) != 44)
    {
      printf ("ERROR: Failed to write wav header: %s\n", strerror (errno));
      return 1;
    }
  return 0;
}

나는 불리는 함수를 발견했다 WAVAPPEND 얼마 전에 Mathworks의 파일 교환 사이트에서. 나는 그것을 사용하지 않았기 때문에 그것이 작동하는지 또는 당신이하려는 일에 적합한 지 확실하지 않지만 아마도 당신에게 유용 할 것입니다.

좋아요...난 여기서 5년이나 늦었어...하지만 난 그냥 나 자신을 위해 이 일을 했고 거기에 해결책을 제시하고 싶었습니다!

matlab에서 큰 wav 파일을 작성하는 동안 메모리 부족과 동일한 문제가 발생했습니다.나는 matlab wavwrite 함수를 편집하여 다음을 사용하여 하드 드라이브에서 데이터를 가져옴으로써 이 문제를 해결했습니다. memmap RAM에 저장된 변수 대신 새 함수로 저장합니다.이렇게 하면 wav 파일을 처음부터 작성할 때 헤더 처리에 대해 걱정할 필요가 없고 외부 응용 프로그램도 필요하지 않으므로 많은 문제를 줄일 수 있습니다.

1) 유형 edit wavwrite함수의 코드를 보려면 해당 코드의 복사본을 새 함수로 저장하세요.

2) 나는 y 의 변수 wavwrite wav 데이터가 포함된 배열에서 내 하드 드라이브에 저장된 각 채널의 데이터 위치를 가리키는 문자열이 있는 셀 배열로 함수를 변환합니다.사용 fwrite 물론 WAV 데이터를 하드 드라이브에 먼저 저장하십시오.함수 시작 시에 저장된 파일 위치를 변환했습니다. y memmap 변수에 넣고 다음과 같이 채널과 샘플 수를 정의했습니다.

다음 줄을 바꾸십시오.

% If input is a vector, force it to be a column:
if ndims(y) > 2,
  error(message('MATLAB:audiovideo:wavwrite:invalidInputFormat'));
end
if size(y,1)==1,
   y = y(:);
end
[samples, channels] = size(y);

이것으로:

% get num of channels
channels = length(y);

%Convert y from strings pointing to wav data to mammap variables allowing access to the data
for i  = 1:length(y)
   y{i} = memmapfile(y{i},'Writable',false,'Format','int16');
end
samples = length(y{1}.Data);

3) 이제 비공개 기능을 편집할 수 있습니다 write_wavedat(fid,fmt).wav 데이터를 쓰는 함수입니다.읽을 수 있도록 중첩된 함수로 변환합니다. y memmap 변수를 전역 변수로 사용하면 값을 함수에 전달하고 RAM을 소모하는 대신 다음과 같이 변경할 수 있습니다.

wav 데이터를 쓰는 줄을 바꾸세요:

if (fwrite(fid, reshape(data',total_samples,1), dtype) ~= total_samples), error(message('MATLAB:audiovideo:wavewrite:failedToWriteSamples')); end

이것으로:

%Divide data into smaller packets for writing
       packetSize = 30*(5e5); %n*5e5 = n Mb of space required
       packets = ceil(samples/packetSize);

       % Write data to file!
       for i=1:length(y)
           for j=1:packets
               if j == packets
                    fwrite(fid, y{i}.Data(((j-1)*packetSize)+1:end), dtype);
               else
                    fwrite(fid, y{i}.Data(((j-1)*packetSize)+1:j*packetSize), dtype);
               end
               disp(['...' num2str(floor(100*((i-1)*packets + j)/(packets*channels))) '% done writing file...']);
           end
       end

그러면 각 memmap 변수의 데이터가 wavfile에 증분적으로 복사됩니다.

4) 그래야 해요!헤더가 자동으로 작성되므로 나머지 코드는 그대로 둘 수 있습니다.다음은 이 기능을 사용하여 대형 2채널 wav 파일을 작성하는 방법의 예입니다.

wavwriteModified({'c:\wavFileinputCh1' 'c:\wavFileinputCh2'},44100,16,'c:\output2ChanWavFile');

matlab이 일반적으로 out of memmory 200MB보다 큰 wav 파일을 쓰는 동안 오류가 발생했습니다.

이를 위해서는 C#이 좋은 선택이 될 것입니다.FileStreams는 작업하기 쉽고 데이터를 청크로 읽고 쓰는 데 사용할 수 있습니다.또한 WAV 파일 헤더를 읽는 것도 비교적 복잡한 작업이지만(RIFF 청크 등을 검색해야 함) 글쓰기 그것은 케이크입니다(헤더 구조를 작성하고 파일 시작 부분에 작성하면 됩니다).

이와 같은 변환을 수행하는 라이브러리가 많이 있지만 그들이 당신이 말하는 거대한 데이터 크기를 처리할 수 있는지 확신할 수 없습니다.그렇더라도 이러한 라이브러리에 더 작은 원시 데이터 덩어리를 공급하려면 프로그래밍 작업을 수행해야 할 것입니다.

자신만의 방법을 작성하는 경우 정규화는 어렵지 않으며 48ksps에서 44.1ksps로 리샘플링하는 것조차 비교적 간단합니다(선형 보간법을 고려하지 않는다는 가정 하에).또한 출력에 대한 더 큰 제어권을 가지게 되므로 하나의 거대한 WAV 파일 대신 작은 WAV 파일 세트를 만드는 것이 더 쉬울 것입니다.

현재 Windows SDK 오디오 캡처 샘플은 마이크에서 데이터를 캡처하고 캡처 된 데이터를 .wav 파일로 저장합니다. 코드는 최적과는 거리가 멀지 만 작동해야합니다.

RIFF 파일 (.WAV 파일은 RIFF 파일)의 크기는 4G로 제한됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top