File: GBAudioClient.m

package info (click to toggle)
sameboy 1.0.2%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 10,528 kB
  • sloc: ansic: 29,948; objc: 22,249; asm: 1,424; pascal: 1,373; makefile: 1,065; xml: 111
file content (134 lines) | stat: -rw-r--r-- 4,020 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import "GBAudioClient.h"

static OSStatus render(
                    GBAudioClient *self,
                    AudioUnitRenderActionFlags *ioActionFlags,
                    const AudioTimeStamp *inTimeStamp,
                    UInt32 inBusNumber,
                    UInt32 inNumberFrames,
                    AudioBufferList *ioData)

{
    GB_sample_t *buffer = (GB_sample_t *)ioData->mBuffers[0].mData;

    self.renderBlock(self.rate, inNumberFrames, buffer);
    
    return noErr;
}

@implementation GBAudioClient
{
    AudioComponentInstance audioUnit;
}

- (id)initWithRendererBlock:(void (^)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer)) block
              andSampleRate:(UInt32) rate
{
    if (!(self = [super init])) { 
        return nil;
    }

    // Configure the search parameters to find the default playback output unit
    // (called the kAudioUnitSubType_RemoteIO on iOS but
    // kAudioUnitSubType_DefaultOutput on Mac OS X)
    AudioComponentDescription defaultOutputDescription;
    defaultOutputDescription.componentType = kAudioUnitType_Output;
#if TARGET_OS_IPHONE
    defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
#else
    defaultOutputDescription.componentSubType = kAudioUnitSubType_DefaultOutput;
#endif
    defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
    defaultOutputDescription.componentFlags = 0;
    defaultOutputDescription.componentFlagsMask = 0;

    // Get the default playback output unit
    AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription);
    if (!defaultOutput) {
        NSLog(@"Can't find default output");
        return nil;
    }

    // Create a new unit based on this that we'll use for output
    OSErr err = AudioComponentInstanceNew(defaultOutput, &audioUnit);
    if (!audioUnit) {
        NSLog(@"Error creating unit: %hd", err);
        return nil;
    }

    // Set our tone rendering function on the unit
    AURenderCallbackStruct input;
    input.inputProc = (void*)render;
    input.inputProcRefCon = (__bridge void *)(self);
    err = AudioUnitSetProperty(audioUnit,
                               kAudioUnitProperty_SetRenderCallback,
                               kAudioUnitScope_Input,
                               0,
                               &input,
                               sizeof(input));
    if (err) {
        NSLog(@"Error setting callback: %hd", err);
        return nil;
    }

    AudioStreamBasicDescription streamFormat;
    streamFormat.mSampleRate = rate;
    streamFormat.mFormatID = kAudioFormatLinearPCM;
    streamFormat.mFormatFlags =
    kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
    streamFormat.mBytesPerPacket = 4;
    streamFormat.mFramesPerPacket = 1;
    streamFormat.mBytesPerFrame = 4;
    streamFormat.mChannelsPerFrame = 2;
    streamFormat.mBitsPerChannel = 2 * 8;
    err = AudioUnitSetProperty (audioUnit,
                                kAudioUnitProperty_StreamFormat,
                                kAudioUnitScope_Input,
                                0,
                                &streamFormat,
                                sizeof(AudioStreamBasicDescription));
    
    if (err) {
        NSLog(@"Error setting stream format: %hd", err);
        return nil;
    }
    err = AudioUnitInitialize(audioUnit);
    if (err) {
        NSLog(@"Error initializing unit: %hd", err);
        return nil;
    }

    self.renderBlock = block;
    _rate = rate;

    return self;
}

-(void) start
{
    OSErr err = AudioOutputUnitStart(audioUnit);
    if (err) {
        NSLog(@"Error starting unit: %hd", err);
        return;
    }
    _playing = true;

}


-(void) stop
{
    AudioOutputUnitStop(audioUnit);
    _playing = false;
}

-(void) dealloc 
{
    [self stop];
    AudioUnitUninitialize(audioUnit);
    AudioComponentInstanceDispose(audioUnit);
}

@end