~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to ios/iOSCoreAudio.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2012- PPSSPP Project.
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
12
// A copy of the GPL 2.0 should have been included with the program.
 
13
// If not, see http://www.gnu.org/licenses/
 
14
 
 
15
// Official git repository and contact information can be found at
 
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
 
17
 
 
18
// This code implements the emulated audio using CoreAudio for iOS
 
19
// Originally written by jtraynham
 
20
 
 
21
#include "iOSCoreAudio.h"
 
22
#include <AudioToolbox/AudioToolbox.h>
 
23
 
 
24
#define SAMPLE_RATE 44100
 
25
 
 
26
#define STREAM_MAX_FRAME_COUNT 2048
 
27
static short stream[STREAM_MAX_FRAME_COUNT * 2 * 2]; // frames * sample size * number of channels
 
28
 
 
29
AudioComponentInstance audioInstance = nil;
 
30
 
 
31
int NativeMix(short *audio, int num_samples);
 
32
 
 
33
OSStatus iOSCoreAudioCallback(void *inRefCon,
 
34
                              AudioUnitRenderActionFlags *ioActionFlags,
 
35
                              const AudioTimeStamp *inTimeStamp,
 
36
                              UInt32 inBusNumber,
 
37
                              UInt32 inNumberFrames,
 
38
                              AudioBufferList *ioData)
 
39
{
 
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;
 
46
        return noErr;
 
47
    }
 
48
    
 
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;
 
55
    
 
56
    return noErr;
 
57
}
 
58
 
 
59
void iOSCoreAudioInit()
 
60
{
 
61
    if (!audioInstance) {
 
62
        OSErr err;
 
63
        
 
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);
 
72
        
 
73
        // create our instance
 
74
        err = AudioComponentInstanceNew(defaultOutput, &audioInstance);
 
75
        if (err != noErr) {
 
76
            audioInstance = nil;
 
77
            return;
 
78
        }
 
79
        
 
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,
 
87
                                   0,
 
88
                                   &input,
 
89
                                   sizeof(input));
 
90
        if (err != noErr) {
 
91
            AudioComponentInstanceDispose(audioInstance);
 
92
            audioInstance = nil;
 
93
            return;
 
94
        }
 
95
        
 
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,
 
110
                                   0,
 
111
                                   &streamFormat,
 
112
                                   sizeof(AudioStreamBasicDescription));
 
113
        if (err != noErr) {
 
114
            AudioComponentInstanceDispose(audioInstance);
 
115
            audioInstance = nil;
 
116
            return;
 
117
        }
 
118
        
 
119
        // k, all setup, so init
 
120
        err = AudioUnitInitialize(audioInstance);
 
121
        if (err != noErr) {
 
122
            AudioComponentInstanceDispose(audioInstance);
 
123
            audioInstance = nil;
 
124
            return;
 
125
        }
 
126
        
 
127
        // finally start playback
 
128
        err = AudioOutputUnitStart(audioInstance);
 
129
        if (err != noErr) {
 
130
            AudioUnitUninitialize(audioInstance);
 
131
            AudioComponentInstanceDispose(audioInstance);
 
132
            audioInstance = nil;
 
133
            return;
 
134
        }
 
135
        
 
136
        // we're good to go
 
137
    }
 
138
}
 
139
 
 
140
void iOSCoreAudioShutdown()
 
141
{
 
142
    if (audioInstance) {
 
143
        AudioOutputUnitStop(audioInstance);
 
144
        AudioUnitUninitialize(audioInstance);
 
145
        AudioComponentInstanceDispose(audioInstance);
 
146
        audioInstance = nil;
 
147
    }
 
148
}