forked from decarbonization/PlayerKit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PKCoreAudioDecoder.cpp
144 lines (114 loc) · 3.69 KB
/
PKCoreAudioDecoder.cpp
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
135
136
137
138
139
140
141
142
143
144
/*
* PKCoreAudioDecoder.cpp
* PKLite
*
* Created by Peter MacWhinnie on 5/23/10.
* Copyright 2010 __MyCompanyName__. All rights reserved.
*
*/
#include "PKCoreAudioDecoder.h"
#include "CAStreamBasicDescription.h"
#pragma mark PKCoreAudioDecoder
#pragma mark Lifetime
PKCoreAudioDecoder::PKCoreAudioDecoder(CFURLRef location) :
PKDecoder("PKCoreAudioDecoder"),
mAudioFile(NULL),
mCurrentFrameInFile(0),
mAudioStreamDescription(),
mFileLocation(CFURLRef(CFRetain(location)))
{
OSStatus status = ExtAudioFileOpenURL(location, &mAudioFile);
RBAssertNoErr(status, CFSTR("ExtAudioFileOpenURL failed with error code %ld."), status);
AudioStreamBasicDescription fileDataFormat;
UInt32 dataSize = sizeof(fileDataFormat);
status = ExtAudioFileGetProperty(mAudioFile, kExtAudioFileProperty_FileDataFormat, &dataSize, &fileDataFormat);
RBAssertNoErr(status, CFSTR("ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) failed with error code %ld."), status);
CAStreamBasicDescription format;
format.mSampleRate = kPKCanonicalSampleRate;
format.SetCanonical(2, false);
status = ExtAudioFileSetProperty(mAudioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(format), &format);
RBAssertNoErr(status, CFSTR("ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) failed with error code %ld."), status);
mAudioStreamDescription = format;
}
PKCoreAudioDecoder::~PKCoreAudioDecoder()
{
if(mAudioFile)
{
ExtAudioFileDispose(mAudioFile);
mAudioFile = NULL;
}
if(mFileLocation)
{
CFRelease(mFileLocation);
mFileLocation = NULL;
}
}
#pragma mark -
#pragma mark Attributes
AudioStreamBasicDescription PKCoreAudioDecoder::GetStreamFormat() const
{
return mAudioStreamDescription;
}
CFURLRef PKCoreAudioDecoder::CopyLocation() const
{
return CFURLRef(CFRetain(mFileLocation));
}
#pragma mark -
PKDecoder::FrameLocation PKCoreAudioDecoder::GetTotalNumberOfFrames() const
{
SInt64 length;
UInt32 size = sizeof(length);
if(ExtAudioFileGetProperty(mAudioFile, kExtAudioFileProperty_FileLengthFrames, &size, &length) == noErr)
return length;
return 0;
}
#pragma mark -
bool PKCoreAudioDecoder::CanSeek() const
{
return true;
}
PKDecoder::FrameLocation PKCoreAudioDecoder::GetCurrentFrame() const
{
return mCurrentFrameInFile;
}
void PKCoreAudioDecoder::SetCurrentFrame(PKDecoder::FrameLocation currentFrame)
{
if((currentFrame >= 0) && (currentFrame <= this->GetTotalNumberOfFrames()))
{
if(ExtAudioFileSeek(mAudioFile, currentFrame) == noErr)
mCurrentFrameInFile = currentFrame;
}
}
#pragma mark -
#pragma mark Decoding
UInt32 PKCoreAudioDecoder::FillBuffers(AudioBufferList *buffers, UInt32 numberOfFrames) throw(RBException)
{
OSStatus errorCode = ExtAudioFileRead(mAudioFile, &numberOfFrames, buffers);
RBAssertNoErr(errorCode, CFSTR("ExtAudioFileRead failed with error %ld."), errorCode);
mCurrentFrameInFile += numberOfFrames;
return numberOfFrames;
}
#pragma mark -
#pragma mark Description
static bool CanDecode(CFURLRef fileLocation)
{
AudioFileID audioFile;
if((AudioFileOpenURL(fileLocation, kAudioFileReadPermission, 0, &audioFile) == noErr) && audioFile)
{
return (AudioFileClose(audioFile) == noErr);
}
return false;
}
static CFArrayRef CopySupportedTypes()
{
CFArrayRef types = NULL;
UInt32 size = sizeof(CFArrayRef);
OSStatus error = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AllUTIs, 0, NULL, &size, &types);
RBAssertNoErr(error, CFSTR("AudioFileGetGlobalInfo failed with error code %ld."), error);
return types;
}
static PKDecoder *CreateInstance(CFURLRef fileLocation) throw(RBException)
{
return new PKCoreAudioDecoder(fileLocation);
}
PKDecoder::Description PKCoreAudioDecoderDescription = { &CanDecode, &CopySupportedTypes, &CreateInstance };