주말 내내 iOS에서 오디오 합성을 프로그래밍하는 방법을 배우는 장애물이되었습니다. 몇 년 동안 iOS에서 개발 해왔지만 오디오 합성 측면에 착수하고 있습니다. 지금은 개념을 배우는 데 도움이되는 데모 애플리케이션을 프로그래밍하고 있습니다. 나는 현재 문제없이 오디오 유닛을위한 재생 렌더러에 사인파를 만들고 쌓을 수있었습니다. 그러나 렌더러에서 어떤 일이 일어나고 있는지 이해하고 싶기 때문에 각 왼쪽 및 오른쪽 채널에 2 개의 사인파를 렌더링 할 수 있습니다.iOS 오디오 장치 - 스테레오 사인파 만들기
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = kSampleRate;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerPacket = 2;
audioFormat.mBytesPerFrame = 2;
하려면 :
에서: 현재, 내 초기화 오디오 부분에서 나는 다음과 같이 변경해야한다고 가정
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = kSampleRate;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 2;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerPacket = 4;
audioFormat.mBytesPerFrame = 4;
하지만를, 렌더러는 나에게 다소 그리스어 . 나는 내가 찾을 수있는 튜토리얼이나 샘플 코드를 가지고 일 해왔다. 모노 신호의 컨텍스트에 맞게 작업 할 수는 있지만 렌더러에서 스테레오 신호를 생성 할 수는 없습니다. 내가 원했던 것은 왼쪽 채널의 하나의 고유 주파수와 오른쪽 채널의 다른 주파수입니다. 그러나 솔직히 렌더러가 작동하도록 이해하지 못했습니다. memcpy 함수를 mBuffers [0] 및 mbuffers [1]에 시도했지만 응용 프로그램이 충돌합니다. 내 렌더링은 아래에 있습니다 (현재는 사인파가 겹쳐져 있지만 스테레오 예제에서는 각 채널에서 한 세트의 주파수 만 사용할 수 있습니다).
#define kOutputBus 0
#define kSampleRate 44100
//44100.0f
#define kWaveform (M_PI * 2.0f/kSampleRate)
OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
HomeViewController *me = (HomeViewController *)inRefCon;
static int phase = 1;
static int phase1 = 1;
for(UInt32 i = 0; i < ioData->mNumberBuffers; i++) {
int samples = ioData->mBuffers[i].mDataByteSize/sizeof(SInt16);
SInt16 values[samples];
float waves;
float volume=.5;
float wave1;
for(int j = 0; j < samples; j++) {
waves = 0;
wave1 = 0;
MyManager *sharedManager = [MyManager sharedManager];
wave1 = sin(kWaveform * sharedManager.globalFr1 * phase1)*sharedManager.globalVol1;
if (0.000001f > wave1) {
[me setFr1:sharedManager.globalFr1];
phase1 = 0;
//NSLog(@"switch");
}
waves += wave1;
waves += sin(kWaveform * sharedManager.globalFr2 * phase)*sharedManager.globalVol2;
waves += sin(kWaveform * sharedManager.globalFr3 * phase)*sharedManager.globalVol3;
waves += sin(kWaveform * sharedManager.globalFr4 * phase)*sharedManager.globalVol4;
waves += sin(kWaveform * sharedManager.globalFr5 * phase)*sharedManager.globalVol5;
waves += sin(kWaveform * sharedManager.globalFr6 * phase)*sharedManager.globalVol6;
waves += sin(kWaveform * sharedManager.globalFr7 * phase)*sharedManager.globalVol7;
waves += sin(kWaveform * sharedManager.globalFr8 * phase)*sharedManager.globalVol8;
waves += sin(kWaveform * sharedManager.globalFr9 * phase)*sharedManager.globalVol9;
waves *= 32767/9; // <--------- make sure to divide by how many waves you're stacking
values[j] = (SInt16)waves;
values[j] += values[j]<<16;
phase++;
phase1++;
}
memcpy(ioData->mBuffers[i].mData, values, samples * sizeof(SInt16));
}
return noErr;
}
미리 도움 주셔서 감사합니다!
형식이 인터리브 된 경우 (ASBD가 제안한대로) 샘플은 왼쪽과 오른쪽으로 번갈아 표시되는 한 개의 버퍼에 있습니다 :'LRLRLRLR'. 그러나 콜백에 인터리브 형식을 사용하는 것은 드문 경우입니다. 일반적으로 형식은 OS의 정식 형식입니다. – sbooth
감사. 사실 몇 분 전에 모든 것을 다 알아 냈습니다. 그것은 당신이 말한 것처럼 인터리빙됩니다. 콜백을 통해 루프를 돌면서 사인파를 별개의 L & R 채널로 렌더링하는 방법을 찾아야했습니다. 도와 줘서 고마워 !! – jwkerr
Hello jwkerr, 나는 당신에게 당신의 렌더링 기능 게시에 대해 이야기 할 수 있기를 희망했다. 나는 한동안 작동하는 입체 음향 렌더링을 얻으려고 노력해 왔으며 그것을 얻지 못했습니다. 감사합니다 – VaporwareWolf