나는 점점 가까워지고 있다고 생각한다. 아직도 꽤 길을 잃었다. 나는 놀라운 오디오 엔진 (TAAE)을 사용하여 끝냈다. 지금 AEAudioReceiver를보고 있습니다. 콜백 코드는 다음과 같습니다. 나는 논리적으로 옳다고 생각하지만 올바르게 구현되었다고 생각하지 않는다.
AAC 형식의 ~ 5 초 세그먼트를 기록하십시오.
시도 : AEAudioReciever 콜백을 사용하고 순환 버퍼에 AudioBufferList를 저장하십시오. 레코더 클래스에서 오디오가 수신 된 시간 (초)을 추적합니다. 일단 5 초를 지났 으면 (6 초가 아닌 6 초가 될 수 있습니다). Obj-c 메서드를 호출하여 AEAudioFileWriter를 사용하여 파일을 작성하십시오.
결과 : 작동하지 않았으며 녹음이 매우 느리고 많은 소음으로 계속 들립니다. 나는 기록적인 오디오의 일부를들을 수있다. 그래서 나는 어떤 데이터가 있다는 것을 알지만, 나는 많은 데이터를 잃어 버리는 것과 같다. 나는 이것을 디버깅하는 방법조차 모르겠다. (나는 계속 노력할 것이지만 지금은 꽤 길을 잃는다.)
다른 항목이 AAC로 변환됩니다. 먼저 AAC로 변환하는 것보다 PCM 형식으로 파일을 쓰거나 AAC로 오디오 세그먼트를 변환 할 수 있습니까?
도움을 주셔서 감사합니다.
----- 원형 버퍼 초기화 -----
//trying to get 5 seconds audio, how do I know what the length is if I don't know the frame size yet? and is that even the right question to ask?
TPCircularBufferInit(&_buffer, 1024 * 256);
----- AEAudioReceiver 콜백 ------에 쓰기
static void receiverCallback(__unsafe_unretained MyAudioRecorder *THIS,
__unsafe_unretained AEAudioController *audioController,
void *source,
const AudioTimeStamp *time,
UInt32 frames,
AudioBufferList *audio) {
//store the audio into the buffer
TPCircularBufferCopyAudioBufferList(&THIS->_buffer, audio, time, kTPCircularBufferCopyAll, NULL);
//increase the time interval to track by THIS
THIS.numberOfSecondInCurrentRecording += AEConvertFramesToSeconds(THIS.audioController, frames);
//if number of seconds passed an interval of 5 seconds, than write the last 5 seconds of the buffer to a file
if (THIS.numberOfSecondInCurrentRecording > 5 * THIS->_currentSegment + 1) {
NSLog(@"Segment %d is full, writing file", THIS->_currentSegment);
[THIS writeBufferToFile];
//segment tracking variables
THIS->_numberOfReceiverLoop = 0;
THIS.lastTimeStamp = nil;
THIS->_currentSegment += 1;
} else {
THIS->_numberOfReceiverLoop += 1;
}
// Do something with 'audio'
if (!THIS.lastTimeStamp) {
THIS.lastTimeStamp = (AudioTimeStamp *)time;
}
}
---- 파일합니다 (MyAudioRecorderClass 내부 방법) ----
- (void)writeBufferToFileHandler {
NSString *documentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
objectAtIndex:0];
NSString *filePath = [documentsFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"Segment_%d.aiff", _currentSegment]];
NSError *error = nil;
//setup audio writer, should the buffer be converted to aac first or save the file than convert; and how the heck do you do that?
AEAudioFileWriter *writeFile = [[AEAudioFileWriter alloc] initWithAudioDescription:_audioController.inputAudioDescription];
[writeFile beginWritingToFileAtPath:filePath fileType:kAudioFileAIFFType error:&error];
if (error) {
NSLog(@"Error in init. the file: %@", error);
return;
}
int i = 1;
//loop to write all the AudioBufferLists that is in the Circular Buffer; retrieve the ones based off of the _lastTimeStamp; but I had it in NULL too and worked the same way.
while (1) {
//NSLog(@"Processing buffer file list for segment [%d] and buffer index [%d]", _currentSegment, i);
i += 1;
// Discard any buffers with an incompatible format, in the event of a format change
AudioBufferList *nextBuffer = TPCircularBufferNextBufferList(&_buffer, _lastTimeStamp);
Float32 *frame = (Float32*) &nextBuffer->mBuffers[0].mData;
//if buffer runs out, than we are done writing it and exit loop to close the file
if (!nextBuffer) {
NSLog(@"Ran out of frames, there were [%d] AudioBufferList", i - 1);
break;
}
//Adding audio using AudioFileWriter, is the length correct?
OSStatus status = AEAudioFileWriterAddAudio(writeFile, nextBuffer, sizeof(nextBuffer->mBuffers[0].mDataByteSize));
if (status) {
NSLog(@"Writing Error? %d", status);
}
//consume/clear the buffer
TPCircularBufferConsumeNextBufferList(&_buffer);
}
//close the file and hope it worked
[writeFile finishWriting];
}
----- 오디오 컨트롤러 AudioStreamBasicDescription ------
01,
//interleaved16BitStereoAudioDescription
AudioStreamBasicDescription audioDescription;
memset(&audioDescription, 0, sizeof(audioDescription));
audioDescription.mFormatID = kAudioFormatLinearPCM;
audioDescription.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
audioDescription.mChannelsPerFrame = 2;
audioDescription.mBytesPerPacket = sizeof(SInt16)*audioDescription.mChannelsPerFrame;
audioDescription.mFramesPerPacket = 1;
audioDescription.mBytesPerFrame = sizeof(SInt16)*audioDescription.mChannelsPerFrame;
audioDescription.mBitsPerChannel = 8 * sizeof(SInt16);
audioDescription.mSampleRate = 44100.0;