comparison libmpcodecs/ad_vorbis.c @ 5427:0b5462a620fc

vorbis driver ported, and also fixed a bug, as nominal_bitrate can be -1
author arpi
date Sun, 31 Mar 2002 20:08:19 +0000
parents
children e4c2a5541a6a
comparison
equal deleted inserted replaced
5426:d72dc493c5d3 5427:0b5462a620fc
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 #include "config.h"
7 #include "ad_internal.h"
8
9 #ifdef HAVE_OGGVORBIS
10
11 static ad_info_t info =
12 {
13 "Ogg/Vorbis audio decoder",
14 "libvorbis",
15 AFM_VORBIS,
16 "Felix Buenemann, A'rpi",
17 "libvorbis",
18 "buggy"
19 };
20
21 LIBAD_EXTERN(vorbis)
22
23 #include <math.h>
24 #include <vorbis/codec.h>
25
26 // This struct is also defined in demux_ogg.c => common header ?
27 typedef struct ov_struct_st {
28 vorbis_info vi; /* struct that stores all the static vorbis bitstream
29 settings */
30 vorbis_comment vc; /* struct that stores all the bitstream user comments */
31 vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
32 vorbis_block vb; /* local working space for packet->PCM decode */
33 } ov_struct_t;
34
35 static int preinit(sh_audio_t *sh)
36 {
37 sh->audio_out_minsize=1024*4; // 1024 samples/frame
38 return 1;
39 }
40
41 static int init(sh_audio_t *sh)
42 {
43 ogg_packet op;
44 vorbis_comment vc;
45 struct ov_struct_st *ov;
46
47 /// Init the decoder with the 3 header packets
48 ov = (struct ov_struct_st*)malloc(sizeof(struct ov_struct_st));
49 vorbis_info_init(&ov->vi);
50 vorbis_comment_init(&vc);
51 op.bytes = ds_get_packet(sh->ds,&op.packet);
52 op.b_o_s = 1;
53 /// Header
54 if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
55 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: initial (identification) header broken!\n");
56 free(ov);
57 return 0;
58 }
59 op.bytes = ds_get_packet(sh->ds,&op.packet);
60 op.b_o_s = 0;
61 /// Comments
62 if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
63 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: comment header broken!\n");
64 free(ov);
65 return 0;
66 }
67 op.bytes = ds_get_packet(sh->ds,&op.packet);
68 //// Codebook
69 if(vorbis_synthesis_headerin(&ov->vi,&vc,&op)<0) {
70 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n");
71 free(ov);
72 return 0;
73 } else { /// Print the infos
74 char **ptr=vc.user_comments;
75 while(*ptr){
76 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);
77 ++ptr;
78 }
79 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel, %dHz, %dbit/s %cBR\n",(int)ov->vi.channels,(int)ov->vi.rate,(int)ov->vi.bitrate_nominal,
80 (ov->vi.bitrate_lower!=ov->vi.bitrate_nominal)||(ov->vi.bitrate_upper!=ov->vi.bitrate_nominal)?'V':'C');
81 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);
82 }
83
84 // printf("lower=%d upper=%d \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);
85
86 // Setup the decoder
87 sh->channels=ov->vi.channels;
88 sh->samplerate=ov->vi.rate;
89 // assume 128kbit if bitrate not specified in the header
90 sh->i_bps=((ov->vi.bitrate_nominal>0) ? ov->vi.bitrate_nominal : 128000)/8;
91 sh->context = ov;
92
93 /// Finish the decoder init
94 vorbis_synthesis_init(&ov->vd,&ov->vi);
95 vorbis_block_init(&ov->vd,&ov->vb);
96 mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n");
97
98 return 1;
99 }
100
101 static void uninit(sh_audio_t *sh)
102 {
103 }
104
105 static int control(sh_audio_t *sh,int cmd,void* arg, ...)
106 {
107 switch(cmd)
108 {
109 #if 0
110 case ADCTRL_RESYNC_STREAM:
111 return CONTROL_TRUE;
112 case ADCTRL_SKIP_FRAME:
113 return CONTROL_TRUE;
114 #endif
115 }
116 return CONTROL_UNKNOWN;
117 }
118
119 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen)
120 {
121 int len = 0;
122 int samples;
123 float **pcm;
124 ogg_packet op;
125 char* np;
126 struct ov_struct_st *ov = sh->context;
127 op.b_o_s = op.e_o_s = 0;
128 while(len < minlen) {
129 op.bytes = ds_get_packet(sh->ds,&op.packet);
130 if(!op.packet)
131 break;
132 if(vorbis_synthesis(&ov->vb,&op)==0) /* test for success! */
133 vorbis_synthesis_blockin(&ov->vd,&ov->vb);
134 while((samples=vorbis_synthesis_pcmout(&ov->vd,&pcm))>0){
135 int i,j;
136 int clipflag=0;
137 int convsize=(maxlen-len)/(2*ov->vi.channels); // max size!
138 int bout=(samples<convsize?samples:convsize);
139
140 if(bout<=0) break;
141
142 /* convert floats to 16 bit signed ints (host order) and
143 interleave */
144 for(i=0;i<ov->vi.channels;i++){
145 ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);
146 ogg_int16_t *ptr=convbuffer+i;
147 float *mono=pcm[i];
148 for(j=0;j<bout;j++){
149 #if 1
150 int val=mono[j]*32767.f;
151 #else /* optional dither */
152 int val=mono[j]*32767.f+drand48()-0.5f;
153 #endif
154 /* might as well guard against clipping */
155 if(val>32767){
156 val=32767;
157 clipflag=1;
158 }
159 if(val<-32768){
160 val=-32768;
161 clipflag=1;
162 }
163 *ptr=val;
164 ptr+=ov->vi.channels;
165 }
166 }
167
168 if(clipflag)
169 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(ov->vd.sequence));
170 len+=2*ov->vi.channels*bout;
171 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples);
172 vorbis_synthesis_read(&ov->vd,bout); /* tell libvorbis how
173 many samples we
174 actually consumed */
175 }
176 }
177
178
179
180 return len;
181 }
182
183 #endif /* !HAVE_OGGVORBIS */
184