root/trunk/A52/ACShepA52Decoder.cpp

Revision 63, 38.6 kB (checked in by gbooker, 10 months ago)

Updated the liba52 lib (they switched to svn in some other location and didn't update any of the pointers on the sf site).

Fixes #51

Line 
1 /*
2         A52 / AC-3 Decompression Codec
3         2004, Shepmaster <shepmaster@applesolutions.com>
4        
5         Uses code from the liba52 project and the CoreAudio SDK.
6 */
7
8 //=============================================================================
9 //      Includes
10 //=============================================================================
11
12 #include "ACShepA52Decoder.h"
13 #include "ACCodecDispatch.h"
14 #include "CAStreamBasicDescription.h"
15 #include "CASampleTools.h"
16 #include "CADebugMacros.h"
17
18 //=============================================================================
19 //      ACShepA52Decoder
20 //=============================================================================
21
22 #define kAudioFormatAVIAC3      0x6D732000
23 #define MY_APP_DOMAIN CFSTR("com.cod3r.a52codec")
24
25 //Old
26 #define USE_STEREO_KEY CFSTR("useStereoOverDolby")
27 #define USE_DPLII_KEY CFSTR("useDolbyProLogicII")
28
29 #define DYNAMIC_RANGE_KEY CFSTR("dynamicRange")
30 #define PASSTHROUGH_KEY CFSTR("attemptPassthrough")
31 #define TWO_CHANNEL_KEY CFSTR("twoChannelMode")
32
33 void ACShepA52Decoder::UpgradeOldPrefs()
34 {
35         CFStringRef myApp = MY_APP_DOMAIN;
36         int useStereoOverDolby = 0;
37         CFTypeRef stereo = CFPreferencesCopyAppValue(USE_STEREO_KEY, myApp);
38         if(stereo != NULL)
39         {
40                 CFTypeID type = CFGetTypeID(stereo);
41                 if(type == CFStringGetTypeID())
42                         useStereoOverDolby = CFStringGetIntValue((CFStringRef)stereo);
43                 else if(type == CFNumberGetTypeID())
44                         CFNumberGetValue((CFNumberRef)stereo, kCFNumberIntType, &useStereoOverDolby);
45                 else if(type == CFBooleanGetTypeID())
46                         useStereoOverDolby = CFBooleanGetValue((CFBooleanRef)stereo);
47                 CFRelease(stereo);
48         }
49        
50         int useDPL2 = 0;
51         CFTypeRef dpl2 = CFPreferencesCopyAppValue(USE_DPLII_KEY, myApp);
52         if(dpl2 != NULL)
53         {
54                 CFTypeID type = CFGetTypeID(dpl2);
55                 if(type == CFStringGetTypeID())
56                         useDPL2 = CFStringGetIntValue((CFStringRef)dpl2);
57                 else if(type == CFNumberGetTypeID())
58                         CFNumberGetValue((CFNumberRef)dpl2, kCFNumberIntType, &useDPL2);
59                 else if(type == CFBooleanGetTypeID())
60                         useDPL2 = CFBooleanGetValue((CFBooleanRef)dpl2);
61                 CFRelease(dpl2);
62         }
63        
64         if(useStereoOverDolby)
65                 TwoChannelMode = A52_STEREO;
66         else if(useDPL2)
67                 TwoChannelMode = A52_DOLBY | A52_USE_DPLII;
68         else
69                 TwoChannelMode = A52_DOLBY;
70        
71         CFNumberRef resultingMode = CFNumberCreate(NULL, kCFNumberIntType, &TwoChannelMode);
72         CFPreferencesSetAppValue(TWO_CHANNEL_KEY, resultingMode, myApp);
73         CFRelease(resultingMode);
74         CFPreferencesAppSynchronize(myApp);
75 }
76
77 ACShepA52Decoder::ACShepA52Decoder(UInt32 inInputBufferByteSize) : ACShepA52Codec(inInputBufferByteSize) {
78        
79         //¥¥¥   One issue to talk about here is how do we represent the fact that this
80         //¥¥¥   decoder doesn't care about the number of channels or the sample rate?
81         //¥¥¥   For now, I've implemented it by specifying 0 for the values that don't
82         //¥¥¥   matter. The issue is that 0 can also mean that the value is unknown or
83         //¥¥¥   doesn't apply.
84         //¥¥¥
85         //¥¥¥   Below are examples of both usages, in both the available input and output
86         //¥¥¥   formats. Since the number of channels is 0 (because this decoder doesn't
87         //¥¥¥   care), a lot of the dependant values, like bytes per frame, are unknowable.
88         //¥¥¥
89         //¥¥¥   The reason why this is an issue is that code that tries to figure out how
90         //¥¥¥   to hook this decoder up to other converters is going to have to be very
91         //¥¥¥   careful about being strict enough with format matching that it can always
92         //¥¥¥   be correct, but not too strict that it treats the situations thus created
93         //¥¥¥   as bad matches or, worse yet, an error.
94        
95        
96         /*
97          CAStreamBasicDescription(              double inSampleRate,            UInt32 inFormatID,
98                                                                         UInt32 inBytesPerPacket,        UInt32 inFramesPerPacket,
99                                                                         UInt32 inBytesPerFrame,         UInt32 inChannelsPerFrame,
100                                                                         UInt32 inBitsPerChannel,        UInt32 inFormatFlags);
101          */
102        
103 #ifdef __BIG_ENDIAN__
104         kIntPCMOutFormatFlag   = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked;
105         kFloatPCMOutFormatFlag = kLinearPCMFormatFlagIsFloat             | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked;
106 #else
107         kIntPCMOutFormatFlag   = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
108         kFloatPCMOutFormatFlag = kLinearPCMFormatFlagIsFloat             | kLinearPCMFormatFlagIsPacked;
109 #endif
110         CFStringRef myApp = MY_APP_DOMAIN;
111        
112         CFPreferencesAppSynchronize(myApp);
113         CFTypeRef dynRange = CFPreferencesCopyAppValue(DYNAMIC_RANGE_KEY, myApp);
114         if(dynRange != NULL)
115         {
116                 CFTypeID type = CFGetTypeID(dynRange);
117                 if(type == CFStringGetTypeID())
118                         dynamicRangeCompression = CFStringGetDoubleValue((CFStringRef)dynRange);
119                 else if(type == CFNumberGetTypeID())
120                         CFNumberGetValue((CFNumberRef)dynRange, kCFNumberDoubleType, &dynamicRangeCompression);
121         else
122                         dynamicRangeCompression = 1;
123                 CFRelease(dynRange);
124         }
125         else
126                 dynamicRangeCompression = 1;  //no compression
127        
128         CFTypeRef pass = CFPreferencesCopyAppValue(PASSTHROUGH_KEY, myApp);
129         if(pass != NULL)
130         {
131                 CFTypeID type = CFGetTypeID(pass);
132                 if(type == CFStringGetTypeID())
133                         passthrough = CFStringGetIntValue((CFStringRef)pass);
134                 else if(type == CFNumberGetTypeID())
135                         CFNumberGetValue((CFNumberRef)pass, kCFNumberIntType, &passthrough);
136                 else
137                         passthrough = 0;
138                 CFRelease(pass);
139         }
140         else
141                 passthrough = 0;
142        
143         CFTypeRef twochan = CFPreferencesCopyAppValue(TWO_CHANNEL_KEY, myApp);
144         if(twochan != NULL)
145         {
146                 CFTypeID type = CFGetTypeID(twochan);
147                 if(type == CFStringGetTypeID())
148                         TwoChannelMode = CFStringGetIntValue((CFStringRef)twochan);
149                 else if(type == CFNumberGetTypeID())
150                         CFNumberGetValue((CFNumberRef)twochan, kCFNumberIntType, &TwoChannelMode);
151                 else
152                         TwoChannelMode = 0;
153                 /* sanity checks */
154                 if(TwoChannelMode & A52_CHANNEL_MASK & 0xf7 != 2)
155                 {
156                         /* matches 2 and 10, which is Stereo and Dolby */
157                         TwoChannelMode = A52_DOLBY;
158                 }
159                 TwoChannelMode &= ~A52_ADJUST_LEVEL & ~A52_LFE;
160                 CFRelease(twochan);
161         }
162         else
163                 UpgradeOldPrefs();
164         CFPreferencesSetAppValue(USE_STEREO_KEY, NULL, myApp);
165         CFPreferencesSetAppValue(USE_DPLII_KEY, NULL, myApp);
166
167         static int sample_rates[] = {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 6000, 5512, 4000};
168         for (int sample_index = 0; sample_index < 12; sample_index ++)
169         {
170                 for (int channels = 1; channels <= 6; channels++) {
171                         //      This decoder only takes an A/52 or AC-3 stream as it's input
172                         CAStreamBasicDescription theInputFormat1(sample_rates[sample_index], kAudioFormatAC3, 0, 256*6, 0, channels, 0, 0);
173                         AddInputFormat(theInputFormat1);
174                         CAStreamBasicDescription theInputFormat2(sample_rates[sample_index], kAudioFormatAVIAC3, 0, 256*6, 0, channels, 0, 0);
175                         AddInputFormat(theInputFormat2);
176                        
177                         // if two channel mode is engaged and we are not passing through, only set output for 2 channels
178                         if(!passthrough && TwoChannelMode && channels != 2)
179                                 continue;
180                         // Output 16-Bit Ints
181                         CAStreamBasicDescription theOutputFormat1(sample_rates[sample_index], kAudioFormatLinearPCM, 0, 1, 0, channels, 16, kIntPCMOutFormatFlag);
182                         AddOutputFormat(theOutputFormat1);
183                        
184                         if(!passthrough)
185                         {
186                                 // And 32-Bit
187                                 CAStreamBasicDescription theOutputFormat2(sample_rates[sample_index], kAudioFormatLinearPCM, 0, 1, 0, channels, 32, kIntPCMOutFormatFlag);
188                                 AddOutputFormat(theOutputFormat2);
189                                
190                                 // And floats
191                                 CAStreamBasicDescription theOutputFormat3(sample_rates[sample_index], kAudioFormatLinearPCM, 0, 1, 0, channels, 32, kFloatPCMOutFormatFlag);
192                                 AddOutputFormat(theOutputFormat3);
193                         }
194                 }
195         }
196        
197         total_bytes = 0;
198         total_frames = 0;
199         decoder_state = NULL;
200         firstInput = true;
201        
202         remainingBytesFromLastFrame = 0;
203         beginningOfIncompleteHeaderSize = 0;
204                
205         //fprintf(stderr, "ACShepA52Decoder::Constructor: Number of input formats supported: %lu\n", GetNumberSupportedInputFormats());
206         //fprintf(stderr, "ACShepA52Decoder::Constructor: Number of output formats supported: %lu\n", GetNumberSupportedOutputFormats());
207 }
208
209 ACShepA52Decoder::~ACShepA52Decoder() {
210         // fprintf(stderr, "ACShepA52Decoder::Destructor: Total Frames: %ld\n", total_frames);
211         // fprintf(stderr, "ACShepA52Decoder::Destructor: Total Output Bytes: %ld\n", total_bytes);
212 }
213
214 void ACShepA52Decoder::Initialize(const AudioStreamBasicDescription* inInputFormat,
215                                                                          const AudioStreamBasicDescription* inOutputFormat,
216                                                                          const void* inMagicCookie, UInt32 inMagicCookieByteSize) {
217        
218         ACShepA52Codec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
219        
220         //fprintf(stderr, "ACShepA52Decoder::Initialize: Initializing, magic cookie size is %lu\n", inMagicCookieByteSize);
221        
222         // Library setup
223         a52_accel(A52_ACCEL_DJBFFT);
224         decoder_state = a52_init(); // No optimizations here
225         if (decoder_state == NULL) {
226                 fprintf(stderr, "ACShepA52Decoder::Initialize: Umm... liba52 could not be loaded!\n");
227                 fprintf(stderr, "ACShepA52Decoder::Initialize: I don't know what happens next...\n");
228                 //TODO: return some error
229         }
230        
231         firstInput = true;
232 }
233
234 void ACShepA52Decoder::Uninitialize() {
235         if (decoder_state != NULL) {
236                 a52_free(decoder_state);
237                 decoder_state = NULL;
238         }
239        
240         //fprintf(stderr, "ACShepA52Decoder::Uninitialize: Uninitializing\n");
241        
242         //      let our base class clean up it's internal state
243         ACShepA52Codec::Uninitialize();
244 }
245
246
247 void ACShepA52Decoder::Reset() {
248         //fprintf(stderr, "ACShepA52Decoder::Reset: Resetting\n");
249        
250         if (decoder_state != NULL) {
251                 a52_free(decoder_state);
252         }
253         a52_accel(A52_ACCEL_DJBFFT);
254         decoder_state = a52_init();
255        
256         firstInput = true;
257         remainingBytesFromLastFrame = beginningOfIncompleteHeaderSize = 0;
258        
259         //      let our base class clean up it's internal state
260         ACShepA52Codec::Reset();
261 }
262
263 void ACShepA52Decoder::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, bool& outWritable) {
264         //fprintf(stderr, "ACShepA52Decoder::GetPropertyInfo: Asking for property %.*s\n", (int) sizeof(inPropertyID), (char*)&inPropertyID);
265        
266         switch(inPropertyID)
267         {
268                 default:
269                 ACShepA52Codec::GetPropertyInfo(inPropertyID, outPropertyDataSize, outWritable);
270         }
271 }
272
273 void ACShepA52Decoder::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) {
274        
275         //fprintf(stderr, "ACShepA52Decoder::GetProperty: Asking for property %.*s\n", (int) sizeof(inPropertyID), (char*)&inPropertyID);
276        
277         switch(inPropertyID)
278         {
279 #if TARGET_OS_MAC
280                 case kAudioCodecPropertyNameCFString:
281                 {
282                         if (ioPropertyDataSize != sizeof(CFStringRef)) {
283                                 CODEC_THROW(kAudioCodecBadPropertySizeError);
284                         }
285                        
286                         CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("Shepmaster's A52 decoder"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR(""));
287                         *(CFStringRef*)outPropertyData = name;
288                         break;
289                 }
290 #endif
291
292                        
293                 default:
294                        
295                         ACShepA52Codec::GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
296         }
297 }
298
299
300
301 void ACShepA52Decoder::SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData)
302 {
303         //fprintf(stderr, "ACShepA52Decoder::SetProperty: Asking for property %.*s\n", (int) sizeof(inPropertyID), (char*)&inPropertyID);
304
305         switch(inPropertyID) {
306                 default:
307                
308                 ACShepA52Codec::SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
309         }
310 }
311
312 void ACShepA52Decoder::SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat) {
313         /*
314         fprintf(stderr, "--------------------\n");
315         fprintf(stderr, "Setting input format\n");
316         fprintf(stderr, "Rate: %f\n", inInputFormat.mSampleRate);
317         fprintf(stderr, "Format ID: %s\n", inInputFormat.mFormatID == kAudioFormatAC3 ? "kAudioFormatAC3" : "not kAudioFormatAC3");
318         fprintf(stderr, "Bytes per packet: %ld\n", inInputFormat.mBytesPerPacket);
319         fprintf(stderr, "Frames per packet: %ld\n", inInputFormat.mFramesPerPacket);
320         fprintf(stderr, "Bytes per frame: %ld\n", inInputFormat.mBytesPerFrame);
321         fprintf(stderr, "Channels: %ld\n", inInputFormat.mChannelsPerFrame);
322         fprintf(stderr, "Bits per Channel: %ld\n", inInputFormat.mBitsPerChannel);
323         fprintf(stderr, "--------------------\n");
324         */
325        
326        
327         if(mIsInitialized) {
328                 CODEC_THROW(kAudioCodecStateError);
329         }
330        
331         //      check to make sure the input format is legal
332         if(inInputFormat.mFormatID != kAudioFormatAC3 && inInputFormat.mFormatID != kAudioFormatAVIAC3) {
333                 DebugMessage("ACShepA52Decoder::SetFormats: only support A/52 and AC-3 for input");
334                 CODEC_THROW(kAudioCodecUnsupportedFormatError);
335         }
336        
337         //      tell our base class about the new format
338         ACShepA52Codec::SetCurrentInputFormat(inInputFormat);
339        
340         //fprintf(stderr, "ACShepA52Decoder::SetCurrentInputFormat: Exiting function\n");
341 }
342
343
344
345 void ACShepA52Decoder::SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat) {
346        
347         /*
348         fprintf(stderr, "--------------------\n");
349         fprintf(stderr, "Setting output format\n");
350         fprintf(stderr, "Rate: %f\n", inOutputFormat.mSampleRate);
351         fprintf(stderr, "Format ID: %s\n", inOutputFormat.mFormatID == kAudioFormatLinearPCM ? "kAudioFormatLinearPCM" : "not kAudioFormatLinearPCM");
352         fprintf(stderr, "Bytes per packet: %ld\n", inOutputFormat.mBytesPerPacket);
353         fprintf(stderr, "Frames per packet: %ld\n", inOutputFormat.mFramesPerPacket);
354         fprintf(stderr, "Bytes per frame: %ld\n", inOutputFormat.mBytesPerFrame);
355         fprintf(stderr, "Channels: %ld\n", inOutputFormat.mChannelsPerFrame);
356         fprintf(stderr, "Bits per Channel: %ld\n", inOutputFormat.mBitsPerChannel);
357         fprintf(stderr, "--------------------\n");
358         */
359        
360        
361         if(mIsInitialized) {
362                 CODEC_THROW(kAudioCodecStateError);
363         }
364        
365         if(inOutputFormat.mFormatID != kAudioFormatLinearPCM) {
366                 DebugMessage("ACShepA52Decoder::SetFormats: only supports linear PCM for output");
367                 CODEC_THROW(kAudioCodecUnsupportedFormatError);
368         }
369        
370         if (! (inOutputFormat.mFormatFlags == kIntPCMOutFormatFlag || inOutputFormat.mFormatFlags == kFloatPCMOutFormatFlag)) {
371                 DebugMessage("ACShepA52Decoder::SetFormats: does not support this form of PCM output");
372                 CODEC_THROW(kAudioCodecUnsupportedFormatError);
373         }
374        
375         if (inOutputFormat.mFormatFlags == kIntPCMOutFormatFlag) {
376                 if (! (inOutputFormat.mBitsPerChannel == 16 || inOutputFormat.mBitsPerChannel == 32)) {
377                         DebugMessage("ACShepA52Decoder::SetFormats: only supports 16 and 32 bit integer PCM");
378                         CODEC_THROW(kAudioCodecUnsupportedFormatError);
379                 }
380         }
381                
382         //      tell our base class about the new format
383         ACShepA52Codec::SetCurrentOutputFormat(inOutputFormat);
384         //fprintf(stderr, "ACShepA52Decoder::SetCurrentOutputFormat: Exiting function\n");
385 }
386
387 static unsigned int ChannelCount(int a52_flags)
388 {
389         int total_channels = 0;
390        
391         switch (a52_flags & A52_CHANNEL_MASK) {
392                
393                 case A52_CHANNEL:
394                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found two independant monaural audio\n");
395                         total_channels = 2;
396                         break;
397                        
398                 case A52_CHANNEL1:
399                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found first of two independant monaural channel audio\n");
400                         total_channels = 1;
401                         break;
402                        
403                 case A52_CHANNEL2:
404                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found second of two independant monaural channel audio\n");
405                         total_channels = 1;
406                         break;
407                        
408                 case A52_MONO:
409                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found monaural audio\n");
410                         total_channels = 1;
411                         break;
412                        
413                 case A52_STEREO:
414                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found stereo audio\n");
415                         total_channels = 2;
416                         break;
417                        
418                 case A52_DOLBY:
419                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found Dolby Surround sound audio\n");
420                         total_channels = 2;
421                         break;
422                        
423                 case A52_3F:
424                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found 3 front channel audio\n");
425                         total_channels = 3;
426                         break;
427                        
428                 case A52_2F1R:
429                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found 2 front & 1 back channel audio\n");
430                         total_channels = 3;
431                         break;
432                        
433                 case A52_3F1R:
434                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found 3 front & 1 back channel audio\n");
435                         total_channels = 4;
436                         break;
437                        
438                 case A52_2F2R:
439                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found 2 front & 2 back channel audio\n");
440                         total_channels = 4;
441                         break;
442                        
443                 case A52_3F2R:
444                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found 3 front & 2 back channel audio\n");
445                         total_channels = 5;
446                         break;
447
448                 default:
449                         //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: No audio stream information found, probably not good!\n");
450                         break;
451         }
452        
453         if (a52_flags & A52_LFE) {
454                 //fprintf(stderr, "ACShepA52Decoder::DetermineStreamParameters: Found LFE channel in audio\n");
455                 total_channels ++;
456         }
457        
458         return total_channels;
459 }
460
461 /*
462  * Custom Dynamic range compression
463  * My logic here:
464  * Two cases
465  * 1) The user requested a compression of 1 or less
466  *              return the typical power rule
467  * 2) The user requested a compression of more than 1 (decompression)
468  *              If the stream's requested compression is less than 1.0 (loud sound), return the normal compression
469  *              If the stream's requested compression is more than 1.0 (soft sound), use power rule (which will make it louder in this case).
470  */
471 static sample_t dynrng_call (sample_t c, void *data)
472 {
473         double *level = (double *)data;
474         float levelToUse = (float)*level;
475         if(c > 1.0 || levelToUse <= 1.0)
476                 return powf(c, levelToUse);
477         else
478                 return c;
479 }
480
481 // Output order of liba52: LFE, left, center, right, left surround, right surround.
482 // Channels missing are skipped
483 // Supposed input to CoreAudio is: left, right, center, LFE, left surround, right surround
484
485 void getChannelMap(int a52_flags, int chanMap[6])
486 {
487         int defaultMap[] = {0, 1, 2, 3, 4, 5};
488         int frontChan = 0;
489         int lfe = a52_flags & A52_LFE ? 1 : 0;
490        
491         memcpy(chanMap, defaultMap, sizeof(defaultMap));
492         switch (a52_flags & A52_CHANNEL_MASK) {
493                 case A52_STEREO:
494                 case A52_DOLBY:
495                 case A52_2F1R:
496                 case A52_2F2R:
497                         chanMap[1] = lfe + 1;
498                         frontChan = 1;
499
500                 case A52_CHANNEL:
501                 case A52_CHANNEL1:
502                 case A52_CHANNEL2:
503                 case A52_MONO:
504                         chanMap[0] = lfe;
505                         frontChan++;
506                         break;
507                        
508                 case A52_3F:
509                 case A52_3F1R:
510                 case A52_3F2R:
511                         chanMap[0] = lfe;
512                         chanMap[1] = lfe + 2;
513                         chanMap[2] = lfe + 1;
514                         frontChan = 3;
515                         break;
516                        
517                 default:
518                         break;
519         }
520         if(lfe)
521                 chanMap[frontChan] = 0;
522 }
523
524 template <class outPtr, class inPtr>
525 UInt32 InterleaveSamples(void *output_data_untyped, UInt32 output_data_offset, sample_t *output_samples, int a52_flags) {
526         inPtr  *cast_samples;
527         outPtr *output_data = (outPtr *)output_data_untyped;
528        
529         cast_samples = (inPtr *)output_samples;
530        
531         int chans = ChannelCount(a52_flags);
532        
533         // each element is the liba52 channel number of the CA channel number of the index
534         int chanMap[6];
535         getChannelMap(a52_flags, chanMap);
536        
537         for (int i = 0; i < 256; i++) {
538                 for (int j = 0; j < chans; j++) {
539                         output_data[chans*i + output_data_offset + j] = cast_samples[i + 256*chanMap[j]];
540                 }
541         }
542        
543         return chans * 256; // Number of 'UInt16' we processed
544 }
545
546
547 UInt32 ACShepA52Decoder::ProduceOutputPackets(void* outOutputData,
548                                                                                            UInt32& ioOutputDataByteSize,
549                                                                                            UInt32& ioNumberPackets,
550                                                                                            AudioStreamPacketDescription* outPacketDescription) {
551        
552         // Basically, we will copy the framework of the IMA decoder, and swap the changes
553         // Most of this code is fairly straight from the command-line one I wrote
554        
555         // ioNumberPackets means how many input packets to process
556        
557         UInt32 theAnswer;                                                               // Return value for function
558        
559         UInt32 bytes_to_read = 0;                                               // How many bytes the decoder will consume per A52 frame
560     int a52_flags = 0;                                                          // A report of the A52 stream channels
561     int a52_samplerate = 0;                                                     // What the rate of the A/52 stream is
562     int a52_bitrate = 0;                                                        // Bitrate of the A/52 Stream
563        
564         Byte *input_data = NULL;                                                // A convenience pointer to the input buffer to process
565         sample_t *output_samples = NULL;                                // A place to put the decoded samples (remember the non-interleaving)
566        
567         UInt32 available_frames = 0;                                    // How many frames of input are in the buffer
568         UInt32 processed_frames = 0;                                    // How many frames have been processed
569         UInt32 frames_to_process = 0;                                   // How many frames we should process
570        
571         sample_t level = 1;                                                             // Range of +/- 1
572         int bias = 0;                                                                   // Centered at 0
573        
574         int output_offset = 0;                                                  // Offset within the output to write to
575         UInt32 output_sample_size = 0;                                  // How big one sample of one channel is in the output
576        
577         UInt32 processedBytes = 0;                                              // How many bytes of data we have created
578        
579        
580         if(!mIsInitialized) {
581                 CODEC_THROW(kAudioCodecStateError);
582         }
583        
584        
585        
586         /*
587         fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Being asked for %ld packets\n", ioNumberPackets);
588         fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Current buffer usage: %ld bytes\n", GetUsedInputBufferByteSize());
589         fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Given %ld bytes of output buffer\n", ioOutputDataByteSize);
590         fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: outPacketDescription is %sNULL\n", (outPacketDescription == NULL ? "" : "not "));
591         fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: processing an output of %u channels\n", (unsigned int)mOutputFormat.mChannelsPerFrame);
592         */
593        
594        
595         // OK, we are told to process ioNumberPackets... can we?
596         // We need to 'prime the pump' and start the decoder on the data, so we can get the info needed
597        
598        
599         // A quick sanity check, to make sure the buffer has data
600         if (GetUsedInputBufferByteSize() <= 0) {
601                 // Tell the system we need more friggin data
602                
603                 ioOutputDataByteSize = 0;
604                 ioNumberPackets = 0;
605                 return kAudioCodecProduceOutputPacketNeedsMoreInputData;
606         }
607        
608        
609         // Get some of the data, in order to calculate sizes
610         UInt32 readLength = 7;
611         input_data = GetBytes(readLength);
612         if (readLength != 7 || SyncA52Stream(bytes_to_read, input_data, a52_flags, a52_samplerate, a52_bitrate, true) ==
613                 kAudioCodecProduceOutputPacketNeedsMoreInputData) {
614                
615                 ioOutputDataByteSize = 0;
616                 ioNumberPackets = 0;
617                 return kAudioCodecProduceOutputPacketNeedsMoreInputData;
618         }
619         //      fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Synced Correctly!\n");
620        
621        
622         // After all that, we now have info about the encoding of this stream
623         // Available frames denotes number of input frames
624         available_frames = (GetUsedInputBufferByteSize() / bytes_to_read);
625         //      fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Available input frames: %ld \n", available_frames);
626        
627        
628         if (available_frames < ioNumberPackets) {
629                 // So, we can't make enough
630                 // We make what we can, then return a need for more input
631                
632                 //              fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Cannot make as many packets as requested\n");
633                 frames_to_process = available_frames;
634                 theAnswer = kAudioCodecProduceOutputPacketNeedsMoreInputData;
635         } else if (available_frames > ioNumberPackets) {
636                 // Aren't we just great!
637                 // Tell that we have more left
638                
639                 //              fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Can make more packets than requested\n");
640                 frames_to_process = ioNumberPackets;
641                 theAnswer = kAudioCodecProduceOutputPacketSuccessHasMore;
642         } else {
643                 // Aren't we just average!
644                 // Exactly right amount
645                
646                 //              fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Can only make as many packets as requested\n");
647                 frames_to_process = ioNumberPackets;
648                 theAnswer = kAudioCodecProduceOutputPacketSuccess;
649         }
650        
651         // Need to know what kind of output data to tally up   
652         if (mOutputFormat.mFormatFlags == kIntPCMOutFormatFlag) {
653                 if (mOutputFormat.mBitsPerChannel == 16) {
654                         output_sample_size = sizeof(UInt16);
655                 } else {
656                         output_sample_size = sizeof(UInt32);
657                 }
658         } else {
659                 output_sample_size = sizeof(float);
660         }
661        
662         UInt32 theOutputByteSize = frames_to_process * 6 * 256 * mOutputFormat.mChannelsPerFrame * output_sample_size; 
663         ThrowIf(ioOutputDataByteSize < theOutputByteSize, static_cast<ComponentResult>(kAudioCodecNotEnoughBufferSpaceError), "ACAppleIMA4Decoder::ProduceOutputPackets: not enough space in the output buffer");
664
665         if (mOutputFormat.mFormatFlags == kIntPCMOutFormatFlag) {
666                 if (mOutputFormat.mBitsPerChannel == 16) {
667                         level = 1;
668                         bias = 384;
669                 } else {
670                         level = 1 << 30;
671                         bias = 0;
672                 }
673         } else {
674                 level = 1;
675                 bias = 0;
676         }
677                
678         while(processed_frames < frames_to_process) {
679                 // Redo the entry, for each loop
680                
681                 input_data = GetBytes(readLength);
682                 if (readLength != 7 || SyncA52Stream(bytes_to_read, input_data, a52_flags, a52_samplerate, a52_bitrate, true) ==
683                         kAudioCodecProduceOutputPacketNeedsMoreInputData) {
684                        
685                         // Each PCM frame = (A52 frames) * (6 blocks/A52 frame) * (256 samples/block) * (# channels) * (sample bytes/channel * sample)
686                         processedBytes = processed_frames * 6 * 256 * mOutputFormat.mChannelsPerFrame * output_sample_size;     
687                        
688                        
689                         total_frames += processed_frames;
690                         total_bytes += processedBytes;
691                        
692                         ioNumberPackets = processed_frames;
693                         ioOutputDataByteSize = processedBytes;
694                         outPacketDescription = NULL;
695                        
696                         return kAudioCodecProduceOutputPacketNeedsMoreInputData;
697                 }
698                
699                 // various data provided by a52
700                
701                 /*
702                 printf("ProduceOutputPackets: A52DEC: Bytes to read: %li\n", bytes_to_read);
703                 printf("ProduceOutputPackets: A52DEC: Flags: %x\n", a52_flags);
704                 printf("ProduceOutputPackets: A52DEC: Samplerate: %i\n", a52_samplerate);
705                 printf("ProduceOutputPackets: A52DEC: Bitrate: %i\n", a52_bitrate);
706                 */
707
708                 // Now ready to do a bit of processing...
709                
710                 if(passthrough)
711                 {
712                         static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
713                         static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x01 };
714                        
715                         uint8_t *myOutputData = (uint8_t *)(outOutputData);
716                        
717                         myOutputData += output_offset * output_sample_size;  //output_offset is in 16-bit ints
718                        
719                         int frameSize = mOutputFormat.mChannelsPerFrame * 2;
720                         memset(myOutputData, 0, frameSize * 256 * 6);
721                         input_data = GetBytes(bytes_to_read);
722                        
723                         if (mOutputFormat.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)
724                         {
725                                 memcpy(myOutputData, p_sync_be, 4);
726                                 myOutputData[frameSize] = input_data[5] & 0x7;
727                                 myOutputData[frameSize+1] = p_sync_be[5];
728                                 myOutputData[frameSize+2] = (bytes_to_read >> 4) & 0xff;
729                                 myOutputData[frameSize+3] = (bytes_to_read << 4) & 0xff;
730                                 unsigned int i;
731                                 int frameNumber;
732                                 for(i=0, frameNumber = 2; i<bytes_to_read; i+=4, frameNumber++)
733                                 {
734                                         int offset = frameNumber * frameSize;
735                                         memcpy(&myOutputData[offset], &input_data[i], 4);
736                                 }
737                         }
738                         else
739                         {
740                                 memcpy(myOutputData, p_sync_le, 4);
741                                 myOutputData[frameSize] = p_sync_le[4];
742                                 myOutputData[frameSize+1] = input_data[5] & 0x7;
743                                 myOutputData[frameSize+2] = (bytes_to_read << 4) & 0xff;
744                                 myOutputData[frameSize+3] = (bytes_to_read >> 4) & 0xff;
745                                 unsigned int i;
746                                 int frameNumber;
747                                 for(i=0, frameNumber = 2; i<bytes_to_read; i+=4, frameNumber++)
748                                 {
749                                         int offset = frameNumber * frameSize;
750                                         myOutputData[offset] = input_data[i+1];
751                                         myOutputData[offset+1] = input_data[i];
752                                         myOutputData[offset+2] = input_data[i+3];
753                                         myOutputData[offset+3] = input_data[i+2];
754                                 }
755                         }
756                         output_offset += mOutputFormat.mChannelsPerFrame * 256 * 6;     //Our framed hack
757                 }
758                 else
759                 {
760                         if(mOutputFormat.mChannelsPerFrame <= 2)
761                         {
762                                 if(mOutputFormat.mChannelsPerFrame == 1)
763                                         // Just mono
764                                         a52_flags = A52_MONO | A52_ADJUST_LEVEL;
765                                 else
766                                         // All we really need is stereophonic, baby
767                                         a52_flags = TwoChannelMode;
768                         }
769                         else if(mOutputFormat.mChannelsPerFrame == ChannelCount(a52_flags))
770                                 //Hope and pray that the channel layout is correct
771                                 a52_flags |= A52_ADJUST_LEVEL;
772                         else
773                         {
774                                 fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: channel count doesn't match; expect odd results\n");
775                                 //Put in some guesses here
776                                 switch(mOutputFormat.mChannelsPerFrame)
777                                 {
778                                         case 3:
779                                                 a52_flags = A52_2F1R | A52_ADJUST_LEVEL;
780                                                 break;
781                                         case 4:
782                                                 a52_flags = A52_2F2R | A52_ADJUST_LEVEL;
783                                                 break;
784                                         case 5:
785                                                 a52_flags = A52_3F2R | A52_ADJUST_LEVEL;
786                                                 break;
787                                         case 6:
788                                                 a52_flags = A52_3F2R | A52_LFE | A52_ADJUST_LEVEL;
789                                                 break;
790                                 }
791                         }
792
793                         readLength = bytes_to_read;
794                         input_data = GetBytes(readLength);
795                         a52_frame(decoder_state, input_data, &a52_flags, &level, bias);
796                         a52_dynrng(decoder_state, dynrng_call, &dynamicRangeCompression);
797                        
798                         // Cycle through the blocks, and actually do stuff
799                         for (int j = 0; j < 6; j++) {
800                                 a52_block(decoder_state);
801                                 output_samples = a52_samples(decoder_state);
802                                
803                                 // Need to know what kind of output data to process     
804                                 if (mOutputFormat.mFormatFlags == kIntPCMOutFormatFlag) {
805                                         if (mOutputFormat.mBitsPerChannel == 16) {
806                                                 /* Use a bias of 384 and a level of 1 to get the range, 383(+) to 385(-).
807                                                    In IEEE floating point, the range is 0x0x43bf8001 to 0x43bf7fff.
808                                                    If you cast these to ints, the range is -32767 to 32767*/
809                                                 output_offset += InterleaveSamples<SInt16, SInt32>(outOutputData, output_offset, output_samples, a52_flags);
810                                         } else {
811                                                 output_offset += InterleaveSamples<SInt32, float>(outOutputData, output_offset, output_samples, a52_flags);
812                                         }
813                                 } else {
814                                         output_offset += InterleaveSamples<float, float>(outOutputData, output_offset, output_samples, a52_flags);
815                                 }
816                        
817                         }
818                 }
819                
820                 // move on in our data stream
821                 ConsumeInputData(bytes_to_read);
822                 processed_frames++;
823         }
824        
825         // Each PCM frame = (A52 frames) * (6 blocks/A52 frame) * (256 samples/block) * (# channels) * (sample bytes/channel * sample)
826         processedBytes = processed_frames * 6 * 256 * mOutputFormat.mChannelsPerFrame * output_sample_size;                     
827                                
828        
829         if (processedBytes > ioOutputDataByteSize) {
830                 fprintf(stderr, "ACShepA52Decoder::ProduceOutputPackets: Not enough output buffer allocated! Bad things happen now.\n");
831         }
832