2014-06-12 4 views
1

오디오 파일에 쓸 _recordingSamples라는 Float32 값 배열이 있습니다. 파일 (4 바이트)를 생성 도착하지만 퀵타임은 열리지 않습니다, 오디오 파일에 float 배열 쓰기

NSString *outputPath = @"/Users/evanjackson/output.caf"; 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
[fileManager createFileAtPath:outputPath contents:nil attributes:nil]; 

AudioStreamBasicDescription _audioFormat; 
_audioFormat.mSampleRate = 44100.0; 
_audioFormat.mFormatID = kAudioFormatLinearPCM; 
_audioFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; 
_audioFormat.mChannelsPerFrame = 1; 
_audioFormat.mBitsPerChannel = 32; 
_audioFormat.mBytesPerFrame = 4; 
_audioFormat.mFramesPerPacket = 1; 
_audioFormat.mBytesPerPacket = _audioFormat.mFramesPerPacket * _audioFormat.mBytesPerFrame; 

UInt32 lengthPropertySize = sizeof(SInt64); 
ExtAudioFileRef filteredAudio; 
NSURL *destinationURL = [NSURL URLWithString:outputPath]; 
OSStatus status = ExtAudioFileCreateWithURL((__bridge CFURLRef)destinationURL, kAudioFileCAFType, &_audioFormat, NULL, kAudioFileFlags_EraseFile, &filteredAudio); 
printf("Status: %d\n", status); 
//ExtAudioFileOpenURL((__bridge CFURLRef)[NSURL fileURLWithPath:outputPath], &filteredAudio); 
const AudioStreamBasicDescription audioFormat = [del audioFormat]; 
status = ExtAudioFileSetProperty(filteredAudio, kExtAudioFileProperty_ClientDataFormat, sizeof(audioFormat), &audioFormat); 
printf("Status: %d\n", status); 
status = ExtAudioFileGetProperty(filteredAudio, kExtAudioFileProperty_FileLengthFrames, &lengthPropertySize, &_recordingLength); 
printf("Status: %d\n", status); 
AudioBufferList *buffers = (AudioBufferList *)malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer)); 
buffers->mNumberBuffers = 1; 
for (int i = 0; i < buffers->mNumberBuffers; i++) { 
    buffers->mBuffers[0].mData = _recordingSamples; 
    buffers->mBuffers[0].mNumberChannels = 1; 
    buffers->mBuffers[0].mDataByteSize = _recordingLength * sizeof(Float32); 
} 

status = ExtAudioFileWrite(filteredAudio, _recordingLength, buffers); 
printf("Status: %d\n", status); 

스테이터스의 모든

0으로 돌아가서 오류를 반환 - : _recordingLength의 값은 약 나는 다음과 같은 코드를 사용하고 390000.입니다 12842 및 컴파일러에서 다음 메시지를 전달합니다.

libc++abi.dylib: terminating with uncaught exception of type std::bad_alloc: std::bad_alloc 
(lldb) 

아무 잘못입니까? 미리 감사드립니다.

답변

1

질문에 게시 한 코드를 스크랩하십시오. 나는 해결책을 여기에서 찾아 냈다 : How to write array of float values to audio file in Core Audio?. 첫 번째 대답을보십시오. 주어진 링크로 가서 소스 코드를 다운로드 한 다음 EAFWrite.h와 EAFWrite.mm을 프로젝트에 추가했습니다. 다음과 같은 기능 writeToFloats을 (2 차원 배열 예)하지만 1 차원 배열로 작업하는 데 필요한, 그래서 수정 :

-(OSStatus) writeFloats:(long)numFrames fromArray:(float *)data 
{ 
    OSStatus err = noErr; 

    if (!data)  return -1; 
    if (!numFrames) return -1; 

    AudioBufferList *abl = AllocateAudioBufferList(mStreamFormat.mChannelsPerFrame, numFrames*sizeof(short)); 
    if (!abl)  return -1; 

    abl->mBuffers[0].mNumberChannels = 1; 
    abl->mBuffers[0].mDataByteSize = numFrames*sizeof(short); 
    short *buffer = (short*)abl->mBuffers[0].mData; 
    for (long v = 0; v < numFrames; v++) { 
     if (data[v] > 0.999) 
      data[v] = 0.999; 
     else if (data[v] < -1) 
      data[v] = -1; 
     buffer[v] = (short)(data[v]*32768.f); 
    } 

    abl->mBuffers[0].mData = buffer; 

    err = ExtAudioFileWrite(mOutputAudioFile, numFrames, abl); 

    DestroyAudioBufferList(abl); 

    if(err != noErr) 
    { 
     char formatID[5]; 
     *(UInt32 *)formatID = CFSwapInt32HostToBig(err); 
     formatID[4] = '\0'; 
     fprintf(stderr, "ExtAudioFileWrite FAILED! %d '%-4.4s'\n",(int)err, formatID); 
     return err; 
    } 

    return err; 

} 

그리고이를 호출하는 클래스는 오디오가 여러 버퍼에서 읽을 수 있다고 가정 함수 :

NSString *outputPath = @"outputFile.caf" 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
[fileManager createFileAtPath:outputPath contents:nil attributes:nil]; 
NSURL* fileURL = [NSURL URLWithString:outputPath]; 

EAFWrite *writer = [[EAFWrite alloc] init]; 
[writer openFileForWrite:fileURL sr:44100.0 channels:1 wordLength:32 type:kAudioFileCAFType]; 
[writer writeFloats:_recordingLength fromArray:_recordingSamples]; 
0

꽤 잔털이 많은 코드입니다.

이 줄 :

AudioBufferList *buffers = 
    (AudioBufferList *)malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer)); 

나에게 의심스러운. sizeof (AudioBufferList)와 sizeof (AudioBuffer)의 합계 인 고정 크기의 버퍼를 할당합니다.

두 변수의 유형은 무엇입니까?

Sizeof는 가리키는 내용의 크기가 아니라 구조의 크기를 반환합니다. 단일 플로트의 크기와 배열의 총 float 수를 곱한 값에 할당 된 버퍼가 필요하다고 생각합니다. (그 _recordingLength입니까?)

이 코드는 어디서 발생 했습니까? 당신이하고있는 일을 자세히 설명해 주실 수 있습니까? 수레의 배열은 어디에서 왔습니까? 무엇이 코드에 얼마나 많은 바이트가 있는지 알려줍니다. 데이터가 메모리에 어디에 저장되어 있습니까? 그 값의 버퍼를 디스크에 쓰는 것은 무엇입니까?

파일이 생성되면 4 바이트 길이가됩니다. 390000 여개의 수레를 저장하려고 시도하는 경우에는 확실히 문제가되는 것 같습니다.

+0

원래 코드 나는 오디오 파일 (.caf)을 _roordingSamples의 배열로 읽었습니다. 나는이 코드를 사용하여 기본적으로 그것을 뒤집어 썼습니다. 다시 말하자면, 오디오 파일에 수레 배열을 다시 써 넣으려고했지만, 이것이 올바른 방법 일지는 확실하지 않습니다. – sonofjack3