1 /*******************************************************************************
2 *                         Goggles Audio Player Library                         *
3 ********************************************************************************
4 *           Copyright (C) 2010-2015 by Sander Jansen. All Rights Reserved      *
5 *                               ---                                            *
6 * This program is free software: you can redistribute it and/or modify         *
7 * it under the terms of the GNU General Public License as published by         *
8 * the Free Software Foundation, either version 3 of the License, or            *
9 * (at your option) any later version.                                          *
10 *                                                                              *
11 * This program is distributed in the hope that it will be useful,              *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of               *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                *
14 * GNU General Public License for more details.                                 *
15 *                                                                              *
16 * You should have received a copy of the GNU General Public License            *
17 * along with this program.  If not, see http://www.gnu.org/licenses.           *
18 ********************************************************************************/
19 #include "ap_defs.h"
20 #include "ap_event_private.h"
21 #include "ap_packet.h"
22 #include "ap_decoder_plugin.h"
23 
24 extern "C" {
25 #include <stdint.h>
26 #include "a52dec/a52.h"
27 }
28 
29 namespace ap {
30 
31 class A52Decoder : public DecoderPlugin {
32 protected:
33   MemoryBuffer  buffer;
34   a52_state_t*  state  = nullptr;
35   Packet*       out    = nullptr;
36   FXlong  stream_position=0;
37 public:
38   A52Decoder(DecoderContext*);
codec() const39   FXuchar codec() const override { return Codec::A52; }
40   FXbool init(ConfigureEvent*) override;
41   FXbool process(Packet*) override;
42   virtual ~A52Decoder();
43   };
44 
A52Decoder(DecoderContext * e)45 A52Decoder::A52Decoder(DecoderContext * e) : DecoderPlugin(e) {
46   state = a52_init(0);
47   }
48 
~A52Decoder()49 A52Decoder::~A52Decoder() {
50   }
51 
init(ConfigureEvent * event)52 FXbool A52Decoder::init(ConfigureEvent*event) {
53   DecoderPlugin::init(event);
54   event->af.setChannels(2);
55   af=event->af;
56   return true;
57   }
58 
59 
process(Packet * in)60 FXbool A52Decoder::process(Packet*in) {
61   FXbool eos    = (in->flags&FLAG_EOS);
62   buffer.append(in->data(),in->size());
63   in->unref();
64 
65   while (buffer.size()>=7) {
66     int flags;
67     int samplerate;
68     int bitrate;
69     int length = a52_syncinfo(buffer.data(),&flags,&samplerate,&bitrate);
70     if (length<=0) {
71       GM_DEBUG_PRINT("[a52] length returned %d\n",length);
72       return false;
73       }
74     else if (buffer.size()<length) return true;
75 
76     int dflags=A52_STEREO;
77     sample_t level = 1.0f;
78     a52_frame (state,buffer.data(),&dflags,&level,0.0f);
79 
80     for (int i=0;i<6;i++) {
81       a52_block(state);
82       sample_t * samples = a52_samples(state);
83 
84       /// Get new buffer
85       if (out==nullptr) {
86         out = context->get_output_packet();
87         if (out==nullptr) return true;
88         out->stream_position=stream_position;
89         out->stream_length=0;
90         out->af=af;
91         }
92 
93       FXfloat * data = out->flt();
94       for (FXint i=0,d=0;i<256;i++) {
95         data[d++] = samples[i];
96         data[d++] = samples[256+i];
97         }
98       out->wroteFrames(256);
99       if (out->availableFrames()<256) {
100         context->post_output_packet(out);
101         }
102       stream_position+=256;
103       }
104     buffer.readBytes(length);
105     }
106   if (eos) {
107     context->post_output_packet(out,true);
108     }
109   return true;
110   }
111 
ap_a52_decoder(DecoderContext * ctx)112 DecoderPlugin * ap_a52_decoder(DecoderContext * ctx) {
113   return new A52Decoder(ctx);
114   }
115 
116 }
117