IOS Audio - Create stereo sine waves

Over the weekend, I hit a stumbling block while learning how to program audio synthesis on iOS. I have been developing on iOS for several years, but I'm just getting into the aspect of audio synthesis. Right now, I'm just programming demos to help me learn concepts. Currently, I can create and add sine waves in the playback player for audio devices without any problems. But I want to understand what is happening in the renderer, so I can display two separate sine waves in each left and right channels. I currently assume that in the sound initialization section I will need to make the following changes:

From:

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;

To:

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;

}

!

+5
1

, , , , .

, , . iOS ( AudioUnits).

( @jwkerr) streamFormat.mChannelsPerFrame = 2; ( streamFormat.mChannelsPerFrame = 1;) createToneUnit. , / , RenderTone():

// Set the left and right buffers independently
Float32 tmp;
Float32 *buffer0 = (Float32 *)ioData->mBuffers[0].mData;
Float32 *buffer1 = (Float32 *)ioData->mBuffers[1].mData;

// Generate the samples
for (UInt32 frame = 0; frame < inNumberFrames; frame++) {
    tmp = sin(theta) * amplitude;

    if (channelLR[0]) buffer0[frame] = tmp; else buffer0[frame] = 0;
    if (channelLR[1]) buffer1[frame] = tmp; else buffer1[frame] = 0;

    theta += theta_increment;
    if (theta > 2.0 * M_PI) theta -= 2.0 * M_PI;
}

, channelLR[2] - bool, , . , , .

+3

All Articles