00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00016
00017 #include "vorbis_soundprovider_generic.h"
00018
00019
00020 CL_VorbisSoundProvider::CL_VorbisSoundProvider(
00021 const std::string &name,
00022 CL_InputSourceProvider *provider,
00023 bool delete_provider)
00024 {
00025 impl = new CL_VorbisSoundProvider_Generic;
00026 impl->name = name;
00027 impl->provider = provider;
00028 impl->delete_provider = delete_provider;
00029
00030 if (provider == NULL)
00031 {
00032 impl->provider = CL_InputSourceProvider::create_file_provider("");
00033 impl->delete_provider = true;
00034 }
00035 }
00036
00037 CL_VorbisSoundProvider::CL_VorbisSoundProvider(
00038 const std::string &name,
00039 CL_ResourceManager *resources)
00040 {
00041 impl = new CL_VorbisSoundProvider_Generic;
00042 impl->name = name;
00043 impl->provider = resources->get_resource_provider();
00044 }
00045
00046 CL_VorbisSoundProvider::~CL_VorbisSoundProvider()
00047 {
00048 if (impl->delete_provider) delete impl->provider;
00049 delete impl;
00050 }
00051
00052 CL_StreamSoundProvider_Session *CL_VorbisSoundProvider::begin_session()
00053 {
00054 return new CL_VorbisStream(impl->provider->open_source(impl->name.c_str()));
00055 }
00056
00057 void CL_VorbisSoundProvider::end_session(CL_StreamSoundProvider_Session *session)
00058 {
00059 delete session;
00060 }
00061
00062
00063
00064 CL_VorbisStream::CL_VorbisStream(CL_InputSource *_input)
00065 : inited(false), input(_input), stream_eof(false)
00066 {
00067 init();
00068 }
00069
00070 CL_VorbisStream::~CL_VorbisStream()
00071 {
00072 deinit();
00073 }
00074
00075 void CL_VorbisStream::init()
00076 {
00077 if (inited) return;
00078
00079 input->seek(0, CL_InputSource::seek_set);
00080
00081 ogg_sync_init(&oy);
00082
00083 char *buffer;
00084 int bytes;
00085
00086 buffer = ogg_sync_buffer(&oy,4096);
00087 bytes = input->read(buffer, 4096);
00088 ogg_sync_wrote(&oy,bytes);
00089
00090
00091 if (ogg_sync_pageout(&oy,&og) !=1)
00092 {
00093
00094 throw CL_Error("Input does not appear to be an Ogg bitstream.");
00095 }
00096
00097
00098
00099 ogg_stream_init(&os,ogg_page_serialno(&og));
00100
00101 vorbis_info_init(&vi);
00102 vorbis_comment_init(&vc);
00103 if (ogg_stream_pagein(&os,&og)<0)
00104 {
00105
00106 throw CL_Error("Error reading first page of Ogg bitstream data.");
00107 }
00108
00109 if (ogg_stream_packetout(&os,&op)!=1)
00110 {
00111
00112 throw CL_Error("Error reading initial header packet.");
00113 }
00114
00115 if (vorbis_synthesis_headerin(&vi,&vc,&op)<0)
00116 {
00117
00118 throw CL_Error("This Ogg bitstream does not contain Vorbis "
00119 "audio data.");
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 int i=0;
00133 while (i<2)
00134 {
00135 while (i<2)
00136 {
00137 int result=ogg_sync_pageout(&oy,&og);
00138 if(result==0) break;
00139
00140
00141 if(result==1)
00142 {
00143 ogg_stream_pagein(&os,&og);
00144
00145
00146
00147
00148 while(i<2)
00149 {
00150 result=ogg_stream_packetout(&os,&op);
00151 if(result==0)break;
00152 if(result==-1)
00153 {
00154
00155
00156 throw CL_Error("Corrupt secondary header.");
00157 }
00158 vorbis_synthesis_headerin(&vi,&vc,&op);
00159 i++;
00160 }
00161 }
00162 }
00163
00164 buffer=ogg_sync_buffer(&oy,4096);
00165 bytes=input->read(buffer,4096);
00166 if(bytes==0 && i<2)
00167 {
00168 throw CL_Error("End of file before finding all Vorbis headers!");
00169 }
00170 ogg_sync_wrote(&oy,bytes);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 vorbis_synthesis_init(&vd,&vi);
00193 vorbis_block_init(&vd,&vb);
00194
00195
00196
00197
00198 }
00199
00200 void CL_VorbisStream::deinit()
00201 {
00202 if (!inited) return;
00203
00204
00205
00206
00207 ogg_stream_clear(&os);
00208
00209
00210
00211
00212 vorbis_block_clear(&vb);
00213 vorbis_dsp_clear(&vd);
00214 vorbis_info_clear(&vi);
00215
00216
00217 ogg_sync_clear(&oy);
00218
00219 delete input;
00220 }
00221
00222 bool CL_VorbisStream::eof() const
00223 {
00224 return stream_eof;
00225 }
00226
00227 void CL_VorbisStream::stop()
00228 {
00229 }
00230
00231 bool CL_VorbisStream::play()
00232 {
00233 if (stream_eof)
00234 {
00235 deinit();
00236 stream_eof = false;
00237 init();
00238 }
00239 return true;
00240 }
00241
00242 bool CL_VorbisStream::set_position(int pos)
00243 {
00244 return false;
00245 }
00246
00247 int CL_VorbisStream::get_data(void *_data_ptr, int data_requested)
00248 {
00249 data_requested /= sizeof(short) * vi.channels;
00250
00251 short *data_ptr = (short *) _data_ptr;
00252 int data_left = data_requested;
00253
00254 while (!eof() && data_left > 0)
00255 {
00256 float **pcm;
00257
00258 int samples = vorbis_synthesis_pcmout(&vd, &pcm);
00259 if (samples <= 0)
00260 {
00261 stream_data();
00262 continue;
00263 }
00264
00265 if (samples > data_left) samples = data_left;
00266
00267 for (int i=0; i<samples; i++)
00268 {
00269 for (int j=0; j<vi.channels; j++)
00270 {
00271 int s = (int) (pcm[j][i] * 32767);
00272 if (s < -32767) s = -32767;
00273 else if (s > 32767) s = 32767;
00274 *(data_ptr++) = (short) s;
00275 }
00276 }
00277
00278 vorbis_synthesis_read(&vd, samples);
00279 data_left -= samples;
00280 }
00281
00282 return (data_requested - data_left) * sizeof(short) * vi.channels;
00283 }
00284
00285 void CL_VorbisStream::stream_data()
00286 {
00287 while (!eof())
00288 {
00289 int result=ogg_stream_packetout(&os,&op);
00290 if (result > 0)
00291 {
00292 if(vorbis_synthesis(&vb,&op)==0)
00293 vorbis_synthesis_blockin(&vd,&vb);
00294 break;
00295 }
00296
00297 while (!eof())
00298 {
00299 int result = ogg_sync_pageout(&oy,&og);
00300 if (result == -1) continue;
00301 if (result == 0)
00302 {
00303 char *buffer=ogg_sync_buffer(&oy,4096);
00304 int bytes=input->read(buffer,4096);
00305 ogg_sync_wrote(&oy,bytes);
00306 if (bytes==0)
00307 {
00308 stream_eof = true;
00309 return;
00310 }
00311 }
00312 else
00313 {
00314 ogg_stream_pagein(&os,&og);
00315 break;
00316 }
00317 }
00318 }
00319 }
00320
00321 int CL_VorbisStream::get_frequency() const
00322 {
00323 return vi.rate;
00324 }
00325
00326 SoundFormat CL_VorbisStream::get_format() const
00327 {
00328 return (vi.channels == 2) ? sf_16bit_signed_stereo : sf_16bit_signed;
00329 }