Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
398 lines (335 loc) · 12.5 KB

AudioFilePlayer.c

File metadata and controls

398 lines (335 loc) · 12.5 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
This file based on Apple sample code. We haven't changed the file name,
so if you want to see the original search for it on apple.com/developer
*/
Feb 21, 2006
Feb 21, 2006
25
#include "SDL_config.h"
Mar 9, 2006
Mar 9, 2006
27
28
29
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AudioFilePlayer.cpp
*/
30
31
32
33
34
35
36
37
38
39
40
#include "AudioFilePlayer.h"
/*
void ThrowResult (OSStatus result, const char* str)
{
SDL_SetError ("Error: %s %d", str, result);
throw result;
}
*/
#if DEBUG
May 28, 2006
May 28, 2006
41
static void
May 29, 2006
May 29, 2006
42
PrintStreamDesc(AudioStreamBasicDescription * inDesc)
May 29, 2006
May 29, 2006
45
printf("Can't print a NULL desc!\n");
May 28, 2006
May 28, 2006
48
May 29, 2006
May 29, 2006
49
50
51
52
53
54
55
56
57
58
printf("- - - - - - - - - - - - - - - - - - - -\n");
printf(" Sample Rate:%f\n", inDesc->mSampleRate);
printf(" Format ID:%s\n", (char *) &inDesc->mFormatID);
printf(" Format Flags:%lX\n", inDesc->mFormatFlags);
printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
printf("- - - - - - - - - - - - - - - - - - - -\n");
May 28, 2006
May 28, 2006
63
static int
May 29, 2006
May 29, 2006
64
AudioFilePlayer_SetDestination(AudioFilePlayer * afp, AudioUnit * inDestUnit)
May 28, 2006
May 28, 2006
66
/*if (afp->mConnected) throw static_cast<OSStatus>(-1); *//* can't set dest if already engaged */
May 28, 2006
May 28, 2006
68
return 0;
May 29, 2006
May 29, 2006
70
SDL_memcpy(&afp->mPlayUnit, inDestUnit, sizeof(afp->mPlayUnit));
71
72
73
OSStatus result = noErr;
May 28, 2006
May 28, 2006
74
75
/* we can "down" cast a component instance to a component */
76
ComponentDescription desc;
May 29, 2006
May 29, 2006
77
result = GetComponentInfo((Component) * inDestUnit, &desc, 0, 0, 0);
May 28, 2006
May 28, 2006
78
79
80
81
82
83
if (result)
return 0; /*THROW_RESULT("GetComponentInfo") */
/* we're going to use this to know which convert routine to call
a v1 audio unit will have a type of 'aunt'
a v2 audio unit will have one of several different types. */
84
85
if (desc.componentType != kAudioUnitComponentType) {
result = badComponentInstance;
May 28, 2006
May 28, 2006
86
87
88
/*THROW_RESULT("BAD COMPONENT") */
if (result)
return 0;
89
90
91
}
/* Set the input format of the audio unit. */
May 29, 2006
May 29, 2006
92
93
94
95
96
97
result = AudioUnitSetProperty(*inDestUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&afp->mFileDescription,
sizeof(afp->mFileDescription));
May 28, 2006
May 28, 2006
98
99
100
/*THROW_RESULT("AudioUnitSetProperty") */
if (result)
return 0;
May 28, 2006
May 28, 2006
104
static void
May 29, 2006
May 29, 2006
105
106
AudioFilePlayer_SetNotifier(AudioFilePlayer * afp,
AudioFilePlayNotifier inNotifier, void *inRefCon)
107
108
109
110
111
{
afp->mNotifier = inNotifier;
afp->mRefCon = inRefCon;
}
May 28, 2006
May 28, 2006
112
static int
May 29, 2006
May 29, 2006
113
AudioFilePlayer_IsConnected(AudioFilePlayer * afp)
114
115
116
117
{
return afp->mConnected;
}
May 28, 2006
May 28, 2006
118
static AudioUnit
May 29, 2006
May 29, 2006
119
AudioFilePlayer_GetDestUnit(AudioFilePlayer * afp)
May 28, 2006
May 28, 2006
121
return afp->mPlayUnit;
May 28, 2006
May 28, 2006
124
static void
May 29, 2006
May 29, 2006
125
AudioFilePlayer_Print(AudioFilePlayer * afp)
May 28, 2006
May 28, 2006
127
#if DEBUG
May 29, 2006
May 29, 2006
128
129
printf("Is Connected:%s\n", (IsConnected()? "true" : "false"));
printf("- - - - - - - - - - - - - - \n");
May 28, 2006
May 28, 2006
133
static void
May 29, 2006
May 29, 2006
134
AudioFilePlayer_SetStartFrame(AudioFilePlayer * afp, int frame)
135
136
137
138
{
SInt64 position = frame * 2352;
afp->mStartFrame = frame;
May 29, 2006
May 29, 2006
139
afp->mAudioFileManager->SetPosition(afp->mAudioFileManager, position);
May 28, 2006
May 28, 2006
142
143
static int
May 29, 2006
May 29, 2006
144
AudioFilePlayer_GetCurrentFrame(AudioFilePlayer * afp)
May 28, 2006
May 28, 2006
146
return afp->mStartFrame +
May 29, 2006
May 29, 2006
147
(afp->mAudioFileManager->GetByteCounter(afp->mAudioFileManager) /
May 28, 2006
May 28, 2006
148
2352);
May 28, 2006
May 28, 2006
150
151
static void
May 29, 2006
May 29, 2006
152
AudioFilePlayer_SetStopFrame(AudioFilePlayer * afp, int frame)
May 28, 2006
May 28, 2006
154
155
SInt64 position = frame * 2352;
May 29, 2006
May 29, 2006
156
afp->mAudioFileManager->SetEndOfFile(afp->mAudioFileManager, position);
May 28, 2006
May 28, 2006
158
159
void
May 29, 2006
May 29, 2006
160
delete_AudioFilePlayer(AudioFilePlayer * afp)
May 28, 2006
May 28, 2006
162
if (afp != NULL) {
May 29, 2006
May 29, 2006
163
afp->Disconnect(afp);
May 28, 2006
May 28, 2006
164
165
if (afp->mAudioFileManager) {
May 29, 2006
May 29, 2006
166
delete_AudioFileManager(afp->mAudioFileManager);
167
168
afp->mAudioFileManager = 0;
}
May 28, 2006
May 28, 2006
169
170
if (afp->mForkRefNum) {
May 29, 2006
May 29, 2006
171
FSCloseFork(afp->mForkRefNum);
172
173
afp->mForkRefNum = 0;
}
May 29, 2006
May 29, 2006
174
SDL_free(afp);
May 28, 2006
May 28, 2006
178
static int
May 29, 2006
May 29, 2006
179
AudioFilePlayer_Connect(AudioFilePlayer * afp)
May 29, 2006
May 29, 2006
182
183
printf("Connect:%x, engaged=%d\n", (int) afp->mPlayUnit,
(afp->mConnected ? 1 : 0));
May 28, 2006
May 28, 2006
185
if (!afp->mConnected) {
May 29, 2006
May 29, 2006
186
if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager))
Mar 9, 2006
Mar 9, 2006
189
/* set the render callback for the file data to be supplied to the sound converter AU */
190
191
192
afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc;
afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager;
May 29, 2006
May 29, 2006
193
194
195
196
197
198
OSStatus result = AudioUnitSetProperty(afp->mPlayUnit,
kAudioUnitProperty_SetInputCallback,
kAudioUnitScope_Input,
0,
&afp->mInputCallback,
sizeof(afp->mInputCallback));
May 28, 2006
May 28, 2006
199
200
if (result)
return 0; /*THROW_RESULT("AudioUnitSetProperty") */
201
202
203
204
205
206
afp->mConnected = 1;
}
return 1;
}
Mar 9, 2006
Mar 9, 2006
207
208
/* warning noted, now please go away ;-) */
/* #warning This should redirect the calling of notification code to some other thread */
May 28, 2006
May 28, 2006
209
static void
May 29, 2006
May 29, 2006
210
AudioFilePlayer_DoNotification(AudioFilePlayer * afp, OSStatus inStatus)
211
212
213
214
{
if (afp->mNotifier) {
(*afp->mNotifier) (afp->mRefCon, inStatus);
} else {
May 29, 2006
May 29, 2006
215
SDL_SetError("Notification posted with no notifier in place");
May 28, 2006
May 28, 2006
216
217
if (inStatus == kAudioFilePlay_FileIsFinished)
May 29, 2006
May 29, 2006
218
afp->Disconnect(afp);
219
else if (inStatus != kAudioFilePlayErr_FilePlayUnderrun)
May 29, 2006
May 29, 2006
220
afp->Disconnect(afp);
May 28, 2006
May 28, 2006
224
static void
May 29, 2006
May 29, 2006
225
AudioFilePlayer_Disconnect(AudioFilePlayer * afp)
May 29, 2006
May 29, 2006
228
229
printf("Disconnect:%x,%ld, engaged=%d\n", (int) afp->mPlayUnit, 0,
(afp->mConnected ? 1 : 0));
May 28, 2006
May 28, 2006
231
if (afp->mConnected) {
232
afp->mConnected = 0;
May 28, 2006
May 28, 2006
233
234
235
afp->mInputCallback.inputProc = 0;
afp->mInputCallback.inputProcRefCon = 0;
May 29, 2006
May 29, 2006
236
237
238
239
240
241
OSStatus result = AudioUnitSetProperty(afp->mPlayUnit,
kAudioUnitProperty_SetInputCallback,
kAudioUnitScope_Input,
0,
&afp->mInputCallback,
sizeof(afp->mInputCallback));
May 28, 2006
May 28, 2006
242
if (result)
May 29, 2006
May 29, 2006
243
244
SDL_SetError("AudioUnitSetProperty:RemoveInputCallback:%ld",
result);
May 28, 2006
May 28, 2006
245
May 29, 2006
May 29, 2006
246
afp->mAudioFileManager->Disconnect(afp->mAudioFileManager);
May 28, 2006
May 28, 2006
250
251
typedef struct
{
252
253
254
255
UInt32 offset;
UInt32 blockSize;
} SSNDData;
May 28, 2006
May 28, 2006
256
static int
May 29, 2006
May 29, 2006
257
258
AudioFilePlayer_OpenFile(AudioFilePlayer * afp, const FSRef * inRef,
SInt64 * outFileDataSize)
259
260
261
262
263
264
265
266
267
268
{
ContainerChunk chunkHeader;
ChunkHeader chunk;
SSNDData ssndData;
OSErr result;
HFSUniStr255 dfName;
ByteCount actual;
SInt64 offset;
Mar 9, 2006
Mar 9, 2006
269
/* Open the data fork of the input file */
May 29, 2006
May 29, 2006
270
result = FSGetDataForkName(&dfName);
May 28, 2006
May 28, 2006
271
272
273
274
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName") */
result =
May 29, 2006
May 29, 2006
275
276
FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm,
&afp->mForkRefNum);
May 28, 2006
May 28, 2006
277
278
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork") */
Mar 9, 2006
Mar 9, 2006
280
/* Read the file header, and check if it's indeed an AIFC file */
May 28, 2006
May 28, 2006
281
result =
May 29, 2006
May 29, 2006
282
283
FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader),
&chunkHeader, &actual);
May 28, 2006
May 28, 2006
284
285
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork") */
286
287
288
if (chunkHeader.ckID != 'FORM') {
result = -1;
May 28, 2006
May 28, 2006
289
290
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'"); */
291
292
293
294
}
if (chunkHeader.formType != 'AIFC') {
result = -1;
May 28, 2006
May 28, 2006
295
296
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'"); */
Mar 9, 2006
Mar 9, 2006
299
300
301
302
/* Search for the SSND chunk. We ignore all compression etc. information
in other chunks. Of course that is kind of evil, but for now we are lazy
and rely on the cdfs to always give us the same fixed format.
TODO: Parse the COMM chunk we currently skip to fill in mFileDescription.
May 28, 2006
May 28, 2006
303
*/
May 28, 2006
May 28, 2006
306
result =
May 29, 2006
May 29, 2006
307
308
FSReadFork(afp->mForkRefNum, fsFromMark, offset,
sizeof(chunk), &chunk, &actual);
May 28, 2006
May 28, 2006
309
310
311
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork") */
Mar 9, 2006
Mar 9, 2006
312
/* Skip the chunk data */
313
offset = chunk.ckSize;
May 28, 2006
May 28, 2006
314
315
}
while (chunk.ckID != 'SSND');
Mar 9, 2006
Mar 9, 2006
317
318
/* Read the header of the SSND chunk. After this, we are positioned right
at the start of the audio data. */
May 28, 2006
May 28, 2006
319
result =
May 29, 2006
May 29, 2006
320
321
FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData),
&ssndData, &actual);
May 28, 2006
May 28, 2006
322
323
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork") */
May 29, 2006
May 29, 2006
325
result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset);
May 28, 2006
May 28, 2006
326
327
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition") */
Mar 9, 2006
Mar 9, 2006
329
/* Data size */
330
331
*outFileDataSize = chunk.ckSize - ssndData.offset - 8;
Mar 9, 2006
Mar 9, 2006
332
/* File format */
333
334
afp->mFileDescription.mSampleRate = 44100;
afp->mFileDescription.mFormatID = kAudioFormatLinearPCM;
May 28, 2006
May 28, 2006
335
336
afp->mFileDescription.mFormatFlags =
kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
337
338
339
340
341
342
343
344
345
afp->mFileDescription.mBytesPerPacket = 4;
afp->mFileDescription.mFramesPerPacket = 1;
afp->mFileDescription.mBytesPerFrame = 4;
afp->mFileDescription.mChannelsPerFrame = 2;
afp->mFileDescription.mBitsPerChannel = 16;
return 1;
}
May 28, 2006
May 28, 2006
346
AudioFilePlayer *
May 29, 2006
May 29, 2006
347
new_AudioFilePlayer(const FSRef * inFileRef)
May 28, 2006
May 28, 2006
349
SInt64 fileDataSize = 0;
May 28, 2006
May 28, 2006
351
AudioFilePlayer *afp =
May 29, 2006
May 29, 2006
352
(AudioFilePlayer *) SDL_malloc(sizeof(AudioFilePlayer));
353
354
if (afp == NULL)
return NULL;
May 29, 2006
May 29, 2006
355
SDL_memset(afp, '\0', sizeof(*afp));
May 28, 2006
May 28, 2006
356
357
#define SET_AUDIOFILEPLAYER_METHOD(m) afp->m = AudioFilePlayer_##m
May 29, 2006
May 29, 2006
358
359
360
361
362
363
364
365
366
367
368
369
SET_AUDIOFILEPLAYER_METHOD(SetDestination);
SET_AUDIOFILEPLAYER_METHOD(SetNotifier);
SET_AUDIOFILEPLAYER_METHOD(SetStartFrame);
SET_AUDIOFILEPLAYER_METHOD(GetCurrentFrame);
SET_AUDIOFILEPLAYER_METHOD(SetStopFrame);
SET_AUDIOFILEPLAYER_METHOD(Connect);
SET_AUDIOFILEPLAYER_METHOD(Disconnect);
SET_AUDIOFILEPLAYER_METHOD(DoNotification);
SET_AUDIOFILEPLAYER_METHOD(IsConnected);
SET_AUDIOFILEPLAYER_METHOD(GetDestUnit);
SET_AUDIOFILEPLAYER_METHOD(Print);
SET_AUDIOFILEPLAYER_METHOD(OpenFile);
May 28, 2006
May 28, 2006
370
371
#undef SET_AUDIOFILEPLAYER_METHOD
May 29, 2006
May 29, 2006
372
373
if (!afp->OpenFile(afp, inFileRef, &fileDataSize)) {
SDL_free(afp);
May 28, 2006
May 28, 2006
376
Mar 9, 2006
Mar 9, 2006
377
/* we want about 4 seconds worth of data for the buffer */
May 28, 2006
May 28, 2006
378
379
380
381
int bytesPerSecond =
(UInt32) (4 * afp->mFileDescription.mSampleRate *
afp->mFileDescription.mBytesPerFrame);
May 29, 2006
May 29, 2006
383
384
printf("File format:\n");
PrintStreamDesc(&afp->mFileDescription);
May 28, 2006
May 28, 2006
386
May 29, 2006
May 29, 2006
387
388
389
afp->mAudioFileManager = new_AudioFileManager(afp, afp->mForkRefNum,
fileDataSize,
bytesPerSecond);
May 28, 2006
May 28, 2006
390
if (afp->mAudioFileManager == NULL) {
May 29, 2006
May 29, 2006
391
delete_AudioFilePlayer(afp);
392
393
394
395
396
397
return NULL;
}
return afp;
}
May 28, 2006
May 28, 2006
398
/* vi: set ts=4 sw=4 expandtab: */