SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
AppleCommon/GBAudioClient.m
1 #import <Foundation/Foundation.h>
2 #import <AudioToolbox/AudioToolbox.h>
3 #import "GBAudioClient.h"
4
5 static OSStatus render(
6 GBAudioClient *self,
7 AudioUnitRenderActionFlags *ioActionFlags,
8 const AudioTimeStamp *inTimeStamp,
9 UInt32 inBusNumber,
10 UInt32 inNumberFrames,
11 AudioBufferList *ioData)
12
13 {
14 GB_sample_t *buffer = (GB_sample_t *)ioData->mBuffers[0].mData;
15
16 self.renderBlock(self.rate, inNumberFrames, buffer);
17
18 return noErr;
19 }
20
21 @implementation GBAudioClient
22 {
23 AudioComponentInstance audioUnit;
24 }
25
26 - (id)initWithRendererBlock:(void (^)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer)) block
27 andSampleRate:(UInt32) rate
28 {
29 if (!(self = [super init])) {
30 return nil;
31 }
32
33 // Configure the search parameters to find the default playback output unit
34 // (called the kAudioUnitSubType_RemoteIO on iOS but
35 // kAudioUnitSubType_DefaultOutput on Mac OS X)
36 AudioComponentDescription defaultOutputDescription;
37 defaultOutputDescription.componentType = kAudioUnitType_Output;
38 #if TARGET_OS_IPHONE
39 defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
40 #else
41 defaultOutputDescription.componentSubType = kAudioUnitSubType_DefaultOutput;
42 #endif
43 defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
44 defaultOutputDescription.componentFlags = 0;
45 defaultOutputDescription.componentFlagsMask = 0;
46
47 // Get the default playback output unit
48 AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription);
49 if (!defaultOutput) {
50 NSLog(@"Can't find default output");
51 return nil;
52 }
53
54 // Create a new unit based on this that we'll use for output
55 OSErr err = AudioComponentInstanceNew(defaultOutput, &audioUnit);
56 if (!audioUnit) {
57 NSLog(@"Error creating unit: %hd", err);
58 return nil;
59 }
60
61 // Set our tone rendering function on the unit
62 AURenderCallbackStruct input;
63 input.inputProc = (void*)render;
64 input.inputProcRefCon = (__bridge void *)(self);
65 err = AudioUnitSetProperty(audioUnit,
66 kAudioUnitProperty_SetRenderCallback,
67 kAudioUnitScope_Input,
68 0,
69 &input,
70 sizeof(input));
71 if (err) {
72 NSLog(@"Error setting callback: %hd", err);
73 return nil;
74 }
75
76 AudioStreamBasicDescription streamFormat;
77 streamFormat.mSampleRate = rate;
78 streamFormat.mFormatID = kAudioFormatLinearPCM;
79 streamFormat.mFormatFlags =
80 kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
81 streamFormat.mBytesPerPacket = 4;
82 streamFormat.mFramesPerPacket = 1;
83 streamFormat.mBytesPerFrame = 4;
84 streamFormat.mChannelsPerFrame = 2;
85 streamFormat.mBitsPerChannel = 2 * 8;
86 err = AudioUnitSetProperty (audioUnit,
87 kAudioUnitProperty_StreamFormat,
88 kAudioUnitScope_Input,
89 0,
90 &streamFormat,
91 sizeof(AudioStreamBasicDescription));
92
93 if (err) {
94 NSLog(@"Error setting stream format: %hd", err);
95 return nil;
96 }
97 err = AudioUnitInitialize(audioUnit);
98 if (err) {
99 NSLog(@"Error initializing unit: %hd", err);
100 return nil;
101 }
102
103 self.renderBlock = block;
104 _rate = rate;
105
106 return self;
107 }
108
109 -(void) start
110 {
111 OSErr err = AudioOutputUnitStart(audioUnit);
112 if (err) {
113 NSLog(@"Error starting unit: %hd", err);
114 return;
115 }
116 _playing = true;
117
118 }
119
120
121 -(void) stop
122 {
123 AudioOutputUnitStop(audioUnit);
124 _playing = false;
125 }
126
127 -(void) dealloc
128 {
129 [self stop];
130 AudioUnitUninitialize(audioUnit);
131 AudioComponentInstanceDispose(audioUnit);
132 }
133
134 @end
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.