1
// Copyright (c) 2012- PPSSPP Project.
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18
// This code implements the emulated audio using CoreAudio for iOS
19
// Originally written by jtraynham
21
#include "iOSCoreAudio.h"
22
#include <AudioToolbox/AudioToolbox.h>
24
#define SAMPLE_RATE 44100
26
#define STREAM_MAX_FRAME_COUNT 2048
27
static short stream[STREAM_MAX_FRAME_COUNT * 2 * 2]; // frames * sample size * number of channels
29
AudioComponentInstance audioInstance = nil;
31
int NativeMix(short *audio, int num_samples);
33
OSStatus iOSCoreAudioCallback(void *inRefCon,
34
AudioUnitRenderActionFlags *ioActionFlags,
35
const AudioTimeStamp *inTimeStamp,
37
UInt32 inNumberFrames,
38
AudioBufferList *ioData)
40
// see if we have any sound to play
41
UInt32 frames = (inNumberFrames > STREAM_MAX_FRAME_COUNT ? STREAM_MAX_FRAME_COUNT : inNumberFrames);
42
UInt32 framesReady = NativeMix(stream, frames);
43
if (framesReady == 0) {
44
// oops, we don't currently have any sound, so return silence
45
*ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
49
// grab the output buffer and copy data into it
50
AudioSampleType *output = (AudioSampleType *)ioData->mBuffers[0].mData;
51
UInt32 bytesReady = framesReady * sizeof(short) * 2;
52
memcpy(output, stream, bytesReady);
53
// make sure and tell it how much audio data is there
54
ioData->mBuffers[0].mDataByteSize = bytesReady;
59
void iOSCoreAudioInit()
64
// first, grab the default output
65
AudioComponentDescription defaultOutputDescription;
66
defaultOutputDescription.componentType = kAudioUnitType_Output;
67
defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
68
defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
69
defaultOutputDescription.componentFlags = 0;
70
defaultOutputDescription.componentFlagsMask = 0;
71
AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription);
73
// create our instance
74
err = AudioComponentInstanceNew(defaultOutput, &audioInstance);
80
// create our callback so we can give it the audio data
81
AURenderCallbackStruct input;
82
input.inputProc = iOSCoreAudioCallback;
83
input.inputProcRefCon = NULL;
84
err = AudioUnitSetProperty(audioInstance,
85
kAudioUnitProperty_SetRenderCallback,
86
kAudioUnitScope_Input,
91
AudioComponentInstanceDispose(audioInstance);
96
// setup the audio format we'll be using (stereo pcm)
97
AudioStreamBasicDescription streamFormat;
98
memset(&streamFormat, 0, sizeof(streamFormat));
99
streamFormat.mSampleRate = SAMPLE_RATE;
100
streamFormat.mFormatID = kAudioFormatLinearPCM;
101
streamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
102
streamFormat.mBitsPerChannel = sizeof(AudioSampleType) * 8;
103
streamFormat.mChannelsPerFrame = 2;
104
streamFormat.mFramesPerPacket = 1;
105
streamFormat.mBytesPerFrame = (streamFormat.mBitsPerChannel / 8) * streamFormat.mChannelsPerFrame;
106
streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame * streamFormat.mFramesPerPacket;
107
err = AudioUnitSetProperty(audioInstance,
108
kAudioUnitProperty_StreamFormat,
109
kAudioUnitScope_Input,
112
sizeof(AudioStreamBasicDescription));
114
AudioComponentInstanceDispose(audioInstance);
119
// k, all setup, so init
120
err = AudioUnitInitialize(audioInstance);
122
AudioComponentInstanceDispose(audioInstance);
127
// finally start playback
128
err = AudioOutputUnitStart(audioInstance);
130
AudioUnitUninitialize(audioInstance);
131
AudioComponentInstanceDispose(audioInstance);
140
void iOSCoreAudioShutdown()
143
AudioOutputUnitStop(audioInstance);
144
AudioUnitUninitialize(audioInstance);
145
AudioComponentInstanceDispose(audioInstance);