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