Add support for MIDI using FluidSynth
[alure.git] / src / streamdec.cpp
blobc1b93bdcbda8c18a76423206893e404759cc552a
1 /*
2 * ALURE OpenAL utility library
3 * Copyright (c) 2009-2010 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 #include "config.h"
26 #include "main.h"
28 #include <string.h>
30 #include <algorithm>
31 #include <vector>
32 #include <memory>
33 #include <string>
34 #include <istream>
35 #include <fstream>
36 #include <iostream>
37 #include <sstream>
40 static inline ALuint read_le32(std::istream *file)
42 ALubyte buffer[4];
43 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
44 return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
47 static inline ALushort read_le16(std::istream *file)
49 ALubyte buffer[2];
50 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
51 return buffer[0] | (buffer[1]<<8);
54 static inline ALuint read_be32(std::istream *file)
56 ALubyte buffer[4];
57 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
58 return (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8) | buffer[3];
61 static inline ALushort read_be16(std::istream *file)
63 ALubyte buffer[2];
64 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
65 return (buffer[0]<<8) | buffer[1];
68 static inline ALuint read_be80extended(std::istream *file)
70 ALubyte buffer[10];
71 if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
72 ALuint mantissa, last = 0;
73 ALubyte exp = buffer[1];
74 exp = 30 - exp;
75 mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
76 while (exp--)
78 last = mantissa;
79 mantissa >>= 1;
81 if((last&1)) mantissa++;
82 return mantissa;
86 struct nullStream : public alureStream {
87 virtual bool IsValid() { return false; }
88 virtual bool GetFormat(ALenum*,ALuint*,ALuint*) { return false; }
89 virtual ALuint GetData(ALubyte*,ALuint) { return 0; }
90 virtual bool Rewind() { return false; }
91 nullStream():alureStream(NULL) {}
95 struct customStream : public alureStream {
96 void *usrFile;
97 ALenum format;
98 ALuint samplerate;
99 ALuint blockAlign;
100 MemDataInfo memInfo;
102 UserCallbacks cb;
104 virtual bool IsValid()
105 { return usrFile != NULL; }
107 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
109 if(format == AL_NONE)
111 if(!cb.get_fmt || !cb.get_fmt(usrFile, &format, &samplerate, &blockAlign))
112 return false;
114 if(DetectBlockAlignment(format) != blockAlign)
115 format = AL_NONE;
118 *fmt = format;
119 *frequency = samplerate;
120 *blockalign = blockAlign;
121 return true;
124 virtual ALuint GetData(ALubyte *data, ALuint bytes)
125 { return cb.decode(usrFile, data, bytes); }
127 virtual bool Rewind()
129 if(cb.rewind && cb.rewind(usrFile))
130 return true;
131 SetError("Rewind failed");
132 return false;
135 customStream(const char *fname, const UserCallbacks &callbacks)
136 : alureStream(NULL), usrFile(NULL), format(0), samplerate(0),
137 blockAlign(0), cb(callbacks)
138 { if(cb.open_file) usrFile = cb.open_file(fname); }
140 customStream(const MemDataInfo &memData, const UserCallbacks &callbacks)
141 : alureStream(NULL), usrFile(NULL), format(0), samplerate(0),
142 blockAlign(0), memInfo(memData), cb(callbacks)
143 { if(cb.open_mem) usrFile = cb.open_mem(memInfo.Data, memInfo.Length); }
145 customStream(void *userdata, ALenum fmt, ALuint srate, const UserCallbacks &callbacks)
146 : alureStream(NULL), usrFile(userdata), format(fmt), samplerate(srate),
147 blockAlign(DetectBlockAlignment(format)), cb(callbacks)
150 virtual ~customStream()
152 if(cb.close && usrFile)
153 cb.close(usrFile);
154 usrFile = NULL;
159 struct wavStream : public alureStream {
160 ALenum format;
161 int samplerate;
162 int blockAlign;
163 int sampleSize;
164 long dataStart;
165 long dataLen;
166 size_t remLen;
168 virtual bool IsValid()
169 { return (dataStart > 0 && format != AL_NONE); }
171 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
173 *fmt = format;
174 *frequency = samplerate;
175 *blockalign = blockAlign;
176 return true;
179 virtual ALuint GetData(ALubyte *data, ALuint bytes)
181 std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
182 fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
184 std::streamsize got = fstream->gcount();
185 got -= got%blockAlign;
186 remLen -= got;
188 if(BigEndian && sampleSize == 16)
190 for(std::streamsize i = 0;i < got;i+=2)
191 swap(data[i], data[i+1]);
193 else if(BigEndian && sampleSize == 32)
195 for(std::streamsize i = 0;i < got;i+=4)
197 swap(data[i+0], data[i+3]);
198 swap(data[i+1], data[i+2]);
201 else if(BigEndian && sampleSize == 64)
203 for(std::streamsize i = 0;i < got;i+=8)
205 swap(data[i+0], data[i+7]);
206 swap(data[i+1], data[i+6]);
207 swap(data[i+2], data[i+5]);
208 swap(data[i+3], data[i+4]);
212 return got;
215 virtual bool Rewind()
217 fstream->clear();
218 if(fstream->seekg(dataStart))
220 remLen = dataLen;
221 return true;
224 SetError("Seek failed");
225 return false;
228 wavStream(std::istream *_fstream)
229 : alureStream(_fstream), format(0), dataStart(0)
231 ALubyte buffer[25];
232 int length;
234 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
235 memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
236 return;
238 while(!dataStart || format == AL_NONE)
240 char tag[4];
241 if(!fstream->read(tag, 4))
242 break;
244 /* read chunk length */
245 length = read_le32(fstream);
247 if(memcmp(tag, "fmt ", 4) == 0 && length >= 16)
249 /* Data type (should be 1 for PCM data, 3 for float PCM data,
250 * and 17 for IMA4 data) */
251 int type = read_le16(fstream);
252 if(type != 0x0001 && type != 0x0003 && type != 0x0011)
253 break;
255 /* mono or stereo data */
256 int channels = read_le16(fstream);
258 /* sample frequency */
259 samplerate = read_le32(fstream);
261 /* skip average bytes per second */
262 fstream->ignore(4);
264 /* bytes per block */
265 blockAlign = read_le16(fstream);
266 if(blockAlign == 0)
267 break;
269 /* bits per sample */
270 sampleSize = read_le16(fstream);
272 length -= 16;
274 /* Look for any extra data and try to find the format */
275 int extrabytes = 0;
276 if(length >= 2)
278 extrabytes = read_le16(fstream);
279 length -= 2;
281 extrabytes = std::min(extrabytes, length);
283 if(type == 0x0001)
284 format = GetSampleFormat(channels, sampleSize, false);
285 else if(type == 0x0003)
286 format = GetSampleFormat(channels, sampleSize, true);
287 else if(type == 0x0011 && extrabytes >= 2)
289 int samples = read_le16(fstream);
290 length -= 2;
292 /* AL_EXT_IMA4 only supports 36 bytes-per-channel block
293 * alignment, which has 65 uncompressed sample frames */
294 if(blockAlign == 36*channels && samples == 65*channels &&
295 alIsExtensionPresent("AL_EXT_IMA4"))
297 if(channels == 1)
298 format = AL_FORMAT_MONO_IMA4;
299 else if(channels == 2)
300 format = AL_FORMAT_STEREO_IMA4;
304 else if(memcmp(tag, "data", 4) == 0)
306 dataStart = fstream->tellg();
307 dataLen = remLen = length;
310 fstream->seekg(length, std::ios_base::cur);
313 if(dataStart > 0 && format != AL_NONE)
314 fstream->seekg(dataStart);
317 virtual ~wavStream()
321 struct aiffStream : public alureStream {
322 ALenum format;
323 int samplerate;
324 int blockAlign;
325 int sampleSize;
326 long dataStart;
327 long dataLen;
328 size_t remLen;
330 virtual bool IsValid()
331 { return (dataStart > 0 && format != AL_NONE); }
333 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
335 *fmt = format;
336 *frequency = samplerate;
337 *blockalign = blockAlign;
338 return true;
341 virtual ALuint GetData(ALubyte *data, ALuint bytes)
343 std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
344 fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
346 std::streamsize got = fstream->gcount();
347 got -= got%blockAlign;
348 remLen -= got;
350 if(LittleEndian)
352 if(sampleSize == 2)
354 for(std::streamsize i = 0;i < got;i+=2)
355 swap(data[i], data[i+1]);
357 else if(sampleSize == 4)
359 for(std::streamsize i = 0;i < got;i+=4)
361 swap(data[i+0], data[i+3]);
362 swap(data[i+1], data[i+2]);
367 return got;
370 virtual bool Rewind()
372 fstream->clear();
373 if(fstream->seekg(dataStart))
375 remLen = dataLen;
376 return true;
379 SetError("Seek failed");
380 return false;
383 aiffStream(std::istream *_fstream)
384 : alureStream(_fstream), format(0), dataStart(0)
386 ALubyte buffer[25];
387 int length;
389 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
390 memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0)
391 return;
393 while(!dataStart || format == AL_NONE)
395 char tag[4];
396 if(!fstream->read(tag, 4))
397 break;
399 /* read chunk length */
400 length = read_be32(fstream);
402 if(memcmp(tag, "COMM", 4) == 0 && length >= 18)
404 /* mono or stereo data */
405 int channels = read_be16(fstream);
407 /* number of sample frames */
408 fstream->ignore(4);
410 /* bits per sample */
411 sampleSize = read_be16(fstream) / 8;
413 /* sample frequency */
414 samplerate = read_be80extended(fstream);
416 /* block alignment */
417 blockAlign = channels * sampleSize;
419 format = GetSampleFormat(channels, sampleSize*8, false);
421 length -= 18;
423 else if(memcmp(tag, "SSND", 4) == 0)
425 dataStart = fstream->tellg();
426 dataStart += 8;
427 dataLen = remLen = length - 8;
430 fstream->seekg(length, std::ios_base::cur);
433 if(dataStart > 0 && format != AL_NONE)
434 fstream->seekg(dataStart);
437 virtual ~aiffStream()
441 #ifdef HAS_SNDFILE
442 struct sndStream : public alureStream {
443 SNDFILE *sndFile;
444 SF_INFO sndInfo;
445 ALenum format;
447 virtual bool IsValid()
448 { return sndFile != NULL; }
450 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
452 if(format == AL_NONE)
453 format = GetSampleFormat(sndInfo.channels, 16, false);
454 *fmt = format;
455 *frequency = sndInfo.samplerate;
456 *blockalign = sndInfo.channels*2;
457 return true;
460 virtual ALuint GetData(ALubyte *data, ALuint bytes)
462 const ALuint frameSize = 2*sndInfo.channels;
463 return psf_readf_short(sndFile, (short*)data, bytes/frameSize) * frameSize;
466 virtual bool Rewind()
468 if(psf_seek(sndFile, 0, SEEK_SET) != -1)
469 return true;
471 SetError("Seek failed");
472 return false;
475 sndStream(std::istream *_fstream)
476 : alureStream(_fstream), sndFile(NULL), format(AL_NONE)
478 memset(&sndInfo, 0, sizeof(sndInfo));
480 if(!sndfile_handle) return;
482 static SF_VIRTUAL_IO streamIO = {
483 get_filelen, seek,
484 read, write, tell
486 sndFile = psf_open_virtual(&streamIO, SFM_READ, &sndInfo, this);
489 virtual ~sndStream()
491 if(sndFile)
492 psf_close(sndFile);
493 sndFile = NULL;
496 private:
497 // libSndFile iostream callbacks
498 static sf_count_t get_filelen(void *user_data)
500 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
501 stream->clear();
503 std::streampos len = -1;
504 std::streampos pos = stream->tellg();
505 if(stream->seekg(0, std::ios_base::end))
507 len = stream->tellg();
508 stream->seekg(pos);
511 return len;
514 static sf_count_t seek(sf_count_t offset, int whence, void *user_data)
516 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
517 stream->clear();
519 if(whence == SEEK_CUR)
520 stream->seekg(offset, std::ios_base::cur);
521 else if(whence == SEEK_SET)
522 stream->seekg(offset, std::ios_base::beg);
523 else if(whence == SEEK_END)
524 stream->seekg(offset, std::ios_base::end);
525 else
526 return -1;
528 return stream->tellg();
531 static sf_count_t read(void *ptr, sf_count_t count, void *user_data)
533 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
534 stream->clear();
535 stream->read(static_cast<char*>(ptr), count);
536 return stream->gcount();
539 static sf_count_t write(const void*, sf_count_t, void*)
540 { return -1; }
542 static sf_count_t tell(void *user_data)
544 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
545 stream->clear();
546 return stream->tellg();
549 #else
550 struct sndStream : public nullStream {
551 sndStream(std::istream*){}
553 #endif
555 #ifdef HAS_VORBISFILE
556 struct oggStream : public alureStream {
557 OggVorbis_File oggFile;
558 vorbis_info *oggInfo;
559 int oggBitstream;
560 ALenum format;
562 virtual bool IsValid()
563 { return oggInfo != NULL; }
565 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
567 if(format == AL_NONE)
568 format = GetSampleFormat(oggInfo->channels, 16, false);
569 *fmt = format;
570 *frequency = oggInfo->rate;
571 *blockalign = oggInfo->channels*2;
572 return true;
575 virtual ALuint GetData(ALubyte *data, ALuint bytes)
577 ALuint got = 0;
578 while(bytes > 0)
580 int res = pov_read(&oggFile, (char*)&data[got], bytes, BigEndian?1:0, 2, 1, &oggBitstream);
581 if(res <= 0)
582 break;
583 bytes -= res;
584 got += res;
586 // 1, 2, and 4 channel files decode into the same channel order as
587 // OpenAL, however 6(5.1), 7(6.1), and 8(7.1) channel files need to be
588 // re-ordered
589 if(oggInfo->channels == 6)
591 ALshort *samples = (ALshort*)data;
592 for(ALuint i = 0;i < got/sizeof(ALshort);i+=6)
594 // OpenAL : FL, FR, FC, LFE, RL, RR
595 // Vorbis : FL, FC, FR, RL, RR, LFE
596 swap(samples[i+1], samples[i+2]);
597 swap(samples[i+3], samples[i+5]);
598 swap(samples[i+4], samples[i+5]);
601 else if(oggInfo->channels == 7)
603 ALshort *samples = (ALshort*)data;
604 for(ALuint i = 0;i < got/sizeof(ALshort);i+=7)
606 // OpenAL : FL, FR, FC, LFE, RC, SL, SR
607 // Vorbis : FL, FC, FR, SL, SR, RC, LFE
608 swap(samples[i+1], samples[i+2]);
609 swap(samples[i+3], samples[i+6]);
610 swap(samples[i+4], samples[i+6]);
611 swap(samples[i+5], samples[i+6]);
614 else if(oggInfo->channels == 8)
616 ALshort *samples = (ALshort*)data;
617 for(ALuint i = 0;i < got/sizeof(ALshort);i+=8)
619 // OpenAL : FL, FR, FC, LFE, RL, RR, SL, SR
620 // Vorbis : FL, FC, FR, SL, SR, RL, RR, LFE
621 swap(samples[i+1], samples[i+2]);
622 swap(samples[i+3], samples[i+7]);
623 swap(samples[i+4], samples[i+5]);
624 swap(samples[i+5], samples[i+6]);
625 swap(samples[i+6], samples[i+7]);
628 return got;
631 virtual bool Rewind()
633 if(pov_pcm_seek(&oggFile, 0) == 0)
634 return true;
636 SetError("Seek failed");
637 return false;
640 oggStream(std::istream *_fstream)
641 : alureStream(_fstream), oggInfo(NULL), oggBitstream(0), format(AL_NONE)
643 if(!vorbisfile_handle) return;
645 const ov_callbacks streamIO = {
646 read, seek, close, tell
649 if(pov_open_callbacks(this, &oggFile, NULL, 0, streamIO) == 0)
651 oggInfo = pov_info(&oggFile, -1);
652 if(!oggInfo)
653 pov_clear(&oggFile);
657 virtual ~oggStream()
659 if(oggInfo)
660 pov_clear(&oggFile);
661 oggInfo = NULL;
664 private:
665 // libVorbisFile iostream callbacks
666 static int seek(void *user_data, ogg_int64_t offset, int whence)
668 std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
669 stream->clear();
671 if(whence == SEEK_CUR)
672 stream->seekg(offset, std::ios_base::cur);
673 else if(whence == SEEK_SET)
674 stream->seekg(offset, std::ios_base::beg);
675 else if(whence == SEEK_END)
676 stream->seekg(offset, std::ios_base::end);
677 else
678 return -1;
680 return stream->tellg();
683 static size_t read(void *ptr, size_t size, size_t nmemb, void *user_data)
685 std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
686 stream->clear();
688 stream->read(static_cast<char*>(ptr), nmemb*size);
689 size_t ret = stream->gcount();
690 return ret/size;
693 static long tell(void *user_data)
695 std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
696 stream->clear();
697 return stream->tellg();
700 static int close(void*)
702 return 0;
705 #else
706 struct oggStream : public nullStream {
707 oggStream(std::istream*){}
709 #endif
711 #ifdef HAS_FLAC
712 struct flacStream : public alureStream {
713 FLAC__StreamDecoder *flacFile;
714 ALenum format;
715 ALuint samplerate;
716 ALuint blockAlign;
717 ALboolean useFloat;
719 std::vector<ALubyte> initialData;
721 ALubyte *outBytes;
722 ALuint outLen;
723 ALuint outTotal;
725 virtual bool IsValid()
726 { return flacFile != NULL; }
728 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
730 *fmt = format;
731 *frequency = samplerate;
732 *blockalign = blockAlign;
733 return true;
736 virtual ALuint GetData(ALubyte *data, ALuint bytes)
738 outBytes = data;
739 outTotal = 0;
740 outLen = bytes;
742 if(initialData.size() > 0)
744 size_t rem = std::min(initialData.size(), (size_t)bytes);
745 memcpy(data, &initialData[0], rem);
746 outTotal += rem;
747 initialData.erase(initialData.begin(), initialData.begin()+rem);
750 while(outTotal < bytes)
752 if(pFLAC__stream_decoder_process_single(flacFile) == false ||
753 pFLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
754 break;
757 return outTotal;
760 virtual bool Rewind()
762 if(pFLAC__stream_decoder_seek_absolute(flacFile, 0) != false)
764 initialData.clear();
765 return true;
768 SetError("Seek failed");
769 return false;
772 flacStream(std::istream *_fstream)
773 : alureStream(_fstream), flacFile(NULL), format(AL_NONE), samplerate(0),
774 blockAlign(0), useFloat(AL_FALSE)
776 if(!flac_handle) return;
778 flacFile = pFLAC__stream_decoder_new();
779 if(flacFile)
781 if(pFLAC__stream_decoder_init_stream(flacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
783 if(InitFlac())
785 // all ok
786 return;
789 pFLAC__stream_decoder_finish(flacFile);
791 pFLAC__stream_decoder_delete(flacFile);
792 flacFile = NULL;
796 virtual ~flacStream()
798 if(flacFile)
800 pFLAC__stream_decoder_finish(flacFile);
801 pFLAC__stream_decoder_delete(flacFile);
802 flacFile = NULL;
806 private:
807 bool InitFlac()
809 // We need to decode some data to be able to get the channel count, bit
810 // depth, and sample rate. It also ensures the file has FLAC data, as
811 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
812 // Ogg files.
813 outLen = 0;
814 outTotal = 0;
815 while(initialData.size() == 0)
817 if(pFLAC__stream_decoder_process_single(flacFile) == false ||
818 pFLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
819 break;
822 if(initialData.size() > 0)
823 return true;
824 return false;
827 static FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder*, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
829 flacStream *self = static_cast<flacStream*>(client_data);
830 ALubyte *data = self->outBytes + self->outTotal;
831 ALuint i = 0;
833 if(self->format == AL_NONE)
835 ALuint bps = frame->header.bits_per_sample;
836 if(bps == 24 || bps == 32)
838 self->format = GetSampleFormat(frame->header.channels, 32, true);
839 if(self->format != AL_NONE)
841 self->useFloat = AL_TRUE;
842 bps = 32;
844 else bps = 16;
846 if(self->format == AL_NONE)
847 self->format = GetSampleFormat(frame->header.channels, bps, false);
848 self->blockAlign = frame->header.channels * bps/8;
849 self->samplerate = frame->header.sample_rate;
852 const ALboolean useFloat = self->useFloat;
853 while(self->outTotal < self->outLen && i < frame->header.blocksize)
855 for(ALuint c = 0;c < frame->header.channels;c++)
857 if(frame->header.bits_per_sample == 8)
858 ((ALubyte*)data)[c] = buffer[c][i]+128;
859 else if(frame->header.bits_per_sample == 16)
860 ((ALshort*)data)[c] = buffer[c][i];
861 else if(frame->header.bits_per_sample == 24)
863 if(useFloat)
864 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
865 buffer[c][i]/(float)0x7FFFFF :
866 buffer[c][i]/(float)0x800000);
867 else
868 ((ALshort*)data)[c] = buffer[c][i]>>8;
870 else if(frame->header.bits_per_sample == 32)
872 if(useFloat)
873 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
874 buffer[c][i]/(float)0x7FFFFFFF :
875 buffer[c][i]/(float)0x80000000u);
876 else
877 ((ALshort*)data)[c] = buffer[c][i]>>16;
880 self->outTotal += self->blockAlign;
881 data += self->blockAlign;
882 i++;
885 if(i < frame->header.blocksize)
887 ALuint blocklen = (frame->header.blocksize-i) *
888 self->blockAlign;
889 ALuint start = self->initialData.size();
891 self->initialData.resize(start+blocklen);
892 data = &self->initialData[start];
894 do {
895 for(ALuint c = 0;c < frame->header.channels;c++)
897 if(frame->header.bits_per_sample == 8)
898 ((ALubyte*)data)[c] = buffer[c][i]+128;
899 else if(frame->header.bits_per_sample == 16)
900 ((ALshort*)data)[c] = buffer[c][i];
901 else if(frame->header.bits_per_sample == 24)
903 if(useFloat)
904 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
905 buffer[c][i]/(float)0x7FFFFF :
906 buffer[c][i]/(float)0x800000);
907 else
908 ((ALshort*)data)[c] = buffer[c][i]>>8;
910 else if(frame->header.bits_per_sample == 32)
912 if(useFloat)
913 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
914 buffer[c][i]/(float)0x7FFFFFFF :
915 buffer[c][i]/(float)0x80000000u);
916 else
917 ((ALshort*)data)[c] = buffer[c][i]>>16;
920 data += self->blockAlign;
921 i++;
922 } while(i < frame->header.blocksize);
925 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
927 static void MetadataCallback(const FLAC__StreamDecoder*,const FLAC__StreamMetadata*,void*)
930 static void ErrorCallback(const FLAC__StreamDecoder*,FLAC__StreamDecoderErrorStatus,void*)
934 static FLAC__StreamDecoderReadStatus ReadCallback(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t *bytes, void *client_data)
936 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
937 stream->clear();
939 if(*bytes <= 0)
940 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
942 stream->read(reinterpret_cast<char*>(buffer), *bytes);
943 *bytes = stream->gcount();
944 if(*bytes == 0 && stream->eof())
945 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
947 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
949 static FLAC__StreamDecoderSeekStatus SeekCallback(const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void *client_data)
951 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
952 stream->clear();
954 if(!stream->seekg(absolute_byte_offset))
955 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
956 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
958 static FLAC__StreamDecoderTellStatus TellCallback(const FLAC__StreamDecoder*, FLAC__uint64 *absolute_byte_offset, void *client_data)
960 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
961 stream->clear();
963 *absolute_byte_offset = stream->tellg();
964 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
966 static FLAC__StreamDecoderLengthStatus LengthCallback(const FLAC__StreamDecoder*, FLAC__uint64 *stream_length, void *client_data)
968 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
969 stream->clear();
971 std::streampos pos = stream->tellg();
972 if(stream->seekg(0, std::ios_base::end))
974 *stream_length = stream->tellg();
975 stream->seekg(pos);
978 if(!stream->good())
979 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
980 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
982 static FLAC__bool EofCallback(const FLAC__StreamDecoder*, void *client_data)
984 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
985 return (stream->eof()) ? true : false;
988 #else
989 struct flacStream : public nullStream {
990 flacStream(std::istream*){}
992 #endif
995 #ifdef HAS_MPG123
996 struct mp3Stream : public alureStream {
997 mpg123_handle *mp3File;
998 long samplerate;
999 int channels;
1000 ALenum format;
1002 virtual bool IsValid()
1003 { return mp3File != NULL; }
1005 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1007 *fmt = format;
1008 *frequency = samplerate;
1009 *blockalign = channels*2;
1010 return true;
1013 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1015 ALuint amt = 0;
1016 while(bytes > 0)
1018 size_t got = 0;
1019 int ret = pmpg123_read(mp3File, data, bytes, &got);
1021 bytes -= got;
1022 data += got;
1023 amt += got;
1025 if(ret == MPG123_NEW_FORMAT)
1027 long newrate;
1028 int newchans, enc;
1029 pmpg123_getformat(mp3File, &newrate, &newchans, &enc);
1030 continue;
1032 if(ret == MPG123_NEED_MORE)
1034 unsigned char data[4096];
1035 fstream->read((char*)data, sizeof(data));
1036 std::streamsize insize = fstream->gcount();
1037 if(insize > 0 && pmpg123_feed(mp3File, data, insize) == MPG123_OK)
1038 continue;
1040 if(got == 0)
1041 break;
1043 return amt;
1046 virtual bool Rewind()
1048 fstream->clear();
1049 std::istream::pos_type oldpos = fstream->tellg();
1050 fstream->seekg(0);
1052 mpg123_handle *newFile = pmpg123_new(NULL, NULL);
1053 if(pmpg123_open_feed(newFile) == MPG123_OK)
1055 unsigned char data[4096];
1056 long newrate;
1057 int newchans;
1058 int enc;
1060 ALuint amt, total = 0;
1061 int ret = MPG123_OK;
1062 do {
1063 fstream->read((char*)data, sizeof(data));
1064 amt = fstream->gcount();
1065 if(amt == 0) break;
1066 total += amt;
1067 ret = pmpg123_decode(newFile, data, amt, NULL, 0, NULL);
1068 } while(ret == MPG123_NEED_MORE && total < 64*1024);
1070 if(ret == MPG123_NEW_FORMAT &&
1071 pmpg123_getformat(newFile, &newrate, &newchans, &enc) == MPG123_OK)
1073 if(pmpg123_format_none(newFile) == MPG123_OK &&
1074 pmpg123_format(newFile, samplerate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
1076 // All OK
1077 pmpg123_delete(mp3File);
1078 mp3File = newFile;
1079 return true;
1082 pmpg123_delete(newFile);
1085 fstream->seekg(oldpos);
1086 SetError("Restart failed");
1087 return false;
1090 mp3Stream(std::istream *_fstream)
1091 : alureStream(_fstream), mp3File(NULL), format(AL_NONE)
1093 if(!mp123_handle) return;
1095 mp3File = pmpg123_new(NULL, NULL);
1096 if(pmpg123_open_feed(mp3File) == MPG123_OK)
1098 unsigned char data[4096];
1099 int enc;
1101 ALuint amt, total = 0;
1102 int ret = MPG123_OK;
1103 do {
1104 fstream->read((char*)data, sizeof(data));
1105 amt = fstream->gcount();
1106 if(amt == 0) break;
1107 total += amt;
1108 ret = pmpg123_decode(mp3File, data, amt, NULL, 0, NULL);
1109 } while(ret == MPG123_NEED_MORE && total < 64*1024);
1111 if(ret == MPG123_NEW_FORMAT &&
1112 pmpg123_getformat(mp3File, &samplerate, &channels, &enc) == MPG123_OK)
1114 format = GetSampleFormat(channels, 16, false);
1115 if(pmpg123_format_none(mp3File) == MPG123_OK &&
1116 pmpg123_format(mp3File, samplerate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
1118 // All OK
1119 return;
1123 pmpg123_delete(mp3File);
1124 mp3File = NULL;
1127 virtual ~mp3Stream()
1129 if(mp3File)
1130 pmpg123_delete(mp3File);
1131 mp3File = NULL;
1134 #else
1135 struct mp3Stream : public nullStream {
1136 mp3Stream(std::istream*){}
1138 #endif
1141 #ifdef HAS_DUMB
1142 struct dumbStream : public alureStream {
1143 DUMBFILE_SYSTEM vfs;
1144 DUMBFILE *dumbFile;
1145 DUH *duh;
1146 DUH_SIGRENDERER *renderer;
1147 std::vector<sample_t> sampleBuf;
1148 ALuint lastOrder;
1149 ALenum format;
1150 ALCint samplerate;
1152 virtual bool IsValid()
1153 { return renderer != NULL; }
1155 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1157 if(format == AL_NONE)
1159 format = GetSampleFormat(2, 32, true);
1160 if(format == AL_NONE)
1161 format = AL_FORMAT_STEREO16;
1163 *fmt = format;
1164 *frequency = samplerate;
1165 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
1166 sizeof(ALfloat));
1167 return true;
1170 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1172 ALuint ret = 0;
1174 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer)) == 0)
1175 return 0;
1177 ALuint sample_count = bytes / ((format==AL_FORMAT_STEREO16) ?
1178 sizeof(ALshort) : sizeof(ALfloat));
1180 sampleBuf.resize(sample_count);
1181 sample_t *samples[] = {
1182 &sampleBuf[0]
1185 pdumb_silence(samples[0], sample_count);
1186 ret = pduh_sigrenderer_generate_samples(renderer, 1.0f, 65536.0f/samplerate, sample_count/2, samples);
1187 ret *= 2;
1188 if(format == AL_FORMAT_STEREO16)
1190 for(ALuint i = 0;i < ret;i++)
1191 ((ALshort*)data)[i] = clamp(samples[0][i]>>8, -32768, 32767);
1193 else
1195 for(ALuint i = 0;i < ret;i++)
1196 ((ALfloat*)data)[i] = ((samples[0][i]>=0) ?
1197 samples[0][i]/(float)0x7FFFFF :
1198 samples[0][i]/(float)0x800000);
1200 ret *= ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) : sizeof(ALfloat));
1202 return ret;
1205 virtual bool Rewind()
1207 DUH_SIGRENDERER *newrenderer = pdumb_it_start_at_order(duh, 2, lastOrder);
1208 if(!newrenderer)
1210 SetError("Could start renderer");
1211 return false;
1213 pduh_end_sigrenderer(renderer);
1214 renderer = newrenderer;
1215 return true;
1218 virtual bool SetOrder(ALuint order)
1220 DUH_SIGRENDERER *newrenderer = pdumb_it_start_at_order(duh, 2, order);
1221 if(!newrenderer)
1223 SetError("Could not set order");
1224 return false;
1226 pduh_end_sigrenderer(renderer);
1227 renderer = newrenderer;
1229 lastOrder = order;
1230 return true;
1233 dumbStream(std::istream *_fstream)
1234 : alureStream(_fstream), dumbFile(NULL), duh(NULL), renderer(NULL),
1235 lastOrder(0), format(AL_NONE), samplerate(48000)
1237 if(!dumb_handle) return;
1239 ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
1240 if(device)
1241 alcGetIntegerv(device, ALC_FREQUENCY, 1, &samplerate);
1243 DUH* (*funcs[])(DUMBFILE*) = {
1244 pdumb_read_it,
1245 pdumb_read_xm,
1246 pdumb_read_s3m,
1247 pdumb_read_mod,
1248 NULL
1251 vfs.open = NULL;
1252 vfs.skip = skip;
1253 vfs.getc = read_char;
1254 vfs.getnc = read;
1255 vfs.close = NULL;
1257 for(size_t i = 0;funcs[i];i++)
1259 dumbFile = pdumbfile_open_ex(this, &vfs);
1260 if(dumbFile)
1262 duh = funcs[i](dumbFile);
1263 if(duh)
1265 renderer = pdumb_it_start_at_order(duh, 2, lastOrder);
1266 if(renderer)
1268 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer), loop_cb, this);
1269 break;
1272 punload_duh(duh);
1273 duh = NULL;
1276 pdumbfile_close(dumbFile);
1277 dumbFile = NULL;
1279 fstream->clear();
1280 fstream->seekg(0);
1284 virtual ~dumbStream()
1286 if(renderer)
1287 pduh_end_sigrenderer(renderer);
1288 renderer = NULL;
1290 if(duh)
1291 punload_duh(duh);
1292 duh = NULL;
1294 if(dumbFile)
1295 pdumbfile_close(dumbFile);
1296 dumbFile = NULL;
1299 private:
1300 // DUMBFILE iostream callbacks
1301 static int skip(void *user_data, long offset)
1303 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1304 stream->clear();
1306 if(stream->seekg(offset, std::ios_base::cur))
1307 return 0;
1308 return -1;
1311 static long read(char *ptr, long size, void *user_data)
1313 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1314 stream->clear();
1316 stream->read(ptr, size);
1317 return stream->gcount();
1320 static int read_char(void *user_data)
1322 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1323 stream->clear();
1325 unsigned char ret;
1326 stream->read(reinterpret_cast<char*>(&ret), 1);
1327 if(stream->gcount() > 0)
1328 return ret;
1329 return -1;
1332 static int loop_cb(void *user_data)
1334 dumbStream *self = static_cast<dumbStream*>(user_data);
1335 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(self->renderer), 0);
1336 return 0;
1339 #else
1340 struct dumbStream : public nullStream {
1341 dumbStream(std::istream*){}
1343 #endif
1346 #ifdef HAS_FLUIDSYNTH
1347 struct fluidStream : public alureStream {
1348 private:
1349 static const ALubyte MIDI_CHANNEL_MASK = 0x0F;
1350 static const ALubyte MIDI_EVENT_MASK = 0xF0;
1352 static const ALubyte MIDI_NOTEOFF = 0x80; // + note + velocity
1353 static const ALubyte MIDI_NOTEON = 0x90; // + note + velocity
1354 static const ALubyte MIDI_POLYPRESS = 0xA0; // + pressure (2 bytes)
1355 static const ALubyte MIDI_CTRLCHANGE = 0xB0; // + ctrl + value
1356 static const ALubyte MIDI_PRGMCHANGE = 0xC0; // + new patch
1357 static const ALubyte MIDI_CHANPRESS = 0xD0; // + pressure (1 byte)
1358 static const ALubyte MIDI_PITCHBEND = 0xE0; // + pitch bend (2 bytes)
1359 static const ALubyte MIDI_SPECIAL = 0xF0; // Special event
1361 static const ALubyte MIDI_SYSEX = 0xF0; // SysEx begin
1362 static const ALubyte MIDI_SYSEXEND = 0xF7; // SysEx end
1363 static const ALubyte MIDI_SONGPOS = 0xF2; // Song position
1364 static const ALubyte MIDI_SONGSEL = 0xF3; // Song select
1365 static const ALubyte MIDI_META = 0xFF; // Meta event begin
1367 static const ALubyte MIDI_META_EOT = 0x2F; // End-of-track
1368 static const ALubyte MIDI_META_TEMPO = 0x51; // Tempo change
1370 struct MidiTrack {
1371 std::vector<ALubyte> data;
1372 size_t Offset;
1373 ALubyte LastEvent;
1374 ALdouble SamplesLeft;
1376 MidiTrack() : Offset(0), LastEvent(0), SamplesLeft(0.)
1378 void Reset()
1380 Offset = 0;
1381 LastEvent = 0;
1382 SamplesLeft = 0.;
1385 MidiTrack& operator=(const MidiTrack &rhs)
1387 data = rhs.data;
1388 Offset = rhs.Offset;
1389 LastEvent = rhs.LastEvent;
1390 SamplesLeft = rhs.SamplesLeft;
1391 return *this;
1394 unsigned long ReadVarLen()
1396 if(Offset >= data.size())
1397 return 0;
1399 unsigned long len = data[Offset]&0x7F;
1400 while((data[Offset]&0x80))
1402 if(++Offset >= data.size())
1403 return 0;
1404 len = (len<<7) | (data[Offset]&0x7F);
1406 Offset++;
1408 return len;
1412 ALuint Divisions;
1413 std::vector<MidiTrack> Tracks;
1415 ALenum format;
1416 ALsizei sampleRate;
1417 ALdouble samplesPerTick;
1419 fluid_settings_t *fluidSettings;
1420 fluid_synth_t *fluidSynth;
1421 int fontID;
1423 public:
1424 virtual bool IsValid()
1425 { return fluidSynth != NULL; }
1427 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1429 if(format == AL_NONE)
1431 format = GetSampleFormat(2, 32, true);
1432 if(format == AL_NONE)
1433 format = AL_FORMAT_STEREO16;
1435 *fmt = format;
1436 *frequency = sampleRate;
1437 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
1438 sizeof(ALfloat));
1439 return true;
1442 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1444 ALuint ret;
1446 if(format == AL_FORMAT_STEREO16)
1448 ALshort *ptr = reinterpret_cast<ALshort*>(data);
1449 ret = FillBuffer(ptr, bytes/2/sizeof(ALshort));
1450 ret *= 2 * sizeof(ALshort);
1452 else
1454 ALfloat *ptr = reinterpret_cast<ALfloat*>(data);
1455 ret = FillBuffer(ptr, bytes/2/sizeof(ALfloat));
1456 ret *= 2 * sizeof(ALfloat);
1459 return ret;
1462 virtual bool Rewind()
1464 for(std::vector<MidiTrack>::iterator i = Tracks.begin(), end = Tracks.end();i != end;i++)
1466 i->Reset();
1467 unsigned long val = i->ReadVarLen();
1468 i->SamplesLeft += val * samplesPerTick;
1470 pfluid_synth_program_reset(fluidSynth);
1471 UpdateTempo(500000);
1472 return true;
1475 fluidStream(std::istream *_fstream)
1476 : alureStream(_fstream), Divisions(100),
1477 format(AL_NONE), sampleRate(48000), samplesPerTick(1.),
1478 fluidSettings(NULL), fluidSynth(NULL), fontID(FLUID_FAILED)
1480 if(!fsynth_handle) return;
1482 ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
1483 if(device)
1484 alcGetIntegerv(device, ALC_FREQUENCY, 1, &sampleRate);
1486 char hdr[4];
1487 if(!fstream->read(hdr, 4))
1488 return;
1490 if(memcmp(hdr, "MThd", 4) == 0)
1492 ALuint len = read_be32(fstream);
1493 if(len != 6)
1494 return;
1496 int type = read_be16(fstream);
1497 if(type != 0 && type != 1)
1498 return;
1500 ALuint numtracks = read_be16(fstream);
1502 Divisions = read_be16(fstream);
1503 UpdateTempo(500000);
1505 Tracks.resize(numtracks);
1506 for(std::vector<MidiTrack>::iterator i = Tracks.begin(), end = Tracks.end();i != end;i++)
1508 if(!fstream->read(hdr, 4) || memcmp(hdr, "MTrk", 4) != 0)
1509 return;
1511 ALuint len = read_be32(fstream);
1512 i->data.resize(len);
1513 if(!fstream->read(reinterpret_cast<char*>(&i->data[0]), len))
1514 return;
1516 unsigned long val = i->ReadVarLen();
1517 i->SamplesLeft += val * samplesPerTick;
1519 SetupSynth();
1523 virtual ~fluidStream()
1525 if(fontID != FLUID_FAILED)
1526 pfluid_synth_sfunload(fluidSynth, fontID, true);
1527 fontID = FLUID_FAILED;
1529 if(fluidSynth != NULL)
1530 pdelete_fluid_synth(fluidSynth);
1531 fluidSynth = NULL;
1533 if(fluidSettings != NULL)
1534 pdelete_fluid_settings(fluidSettings);
1535 fluidSettings = NULL;
1538 private:
1539 template<typename T>
1540 ALuint FillBuffer(T *Buffer, ALuint BufferSamples)
1542 ALuint SamplesInBuffer = 0;
1543 while(SamplesInBuffer < BufferSamples)
1545 // Check if any tracks are still playing and how many samples are waiting to render
1546 size_t TracksPlaying = 0;
1547 ALuint SamplesToDo = BufferSamples - SamplesInBuffer;
1548 for(std::vector<MidiTrack>::iterator i = Tracks.begin(),
1549 end = Tracks.end();i != end;i++)
1551 if(i->Offset < i->data.size())
1553 SamplesToDo = std::min<ALuint>(SamplesToDo, i->SamplesLeft);
1554 TracksPlaying++;
1557 if(TracksPlaying == 0)
1558 break;
1560 if(SamplesToDo == 0)
1562 ProcessMidi();
1563 continue;
1566 // Render samples
1567 WriteSamples(SamplesToDo, Buffer);
1568 Buffer += SamplesToDo*2;
1569 SamplesInBuffer += SamplesToDo;
1571 for(std::vector<MidiTrack>::iterator i = Tracks.begin(),
1572 end = Tracks.end();i != end;i++)
1574 if(i->Offset < i->data.size())
1575 i->SamplesLeft -= SamplesToDo;
1579 return SamplesInBuffer;
1582 void WriteSamples(ALuint count, short *buffer)
1583 { pfluid_synth_write_s16(fluidSynth, count, buffer, 0, 2, buffer, 1, 2); }
1584 void WriteSamples(ALuint count, float *buffer)
1585 { pfluid_synth_write_float(fluidSynth, count, buffer, 0, 2, buffer, 1, 2); }
1587 void ProcessMidi()
1589 ALuint newtempo = 0;
1591 // Process more events
1592 std::vector<MidiTrack>::iterator i=Tracks.begin(), end=Tracks.end();
1593 while(i != end)
1595 if(i->Offset >= i->data.size() || i->SamplesLeft >= 1.)
1597 i++;
1598 continue;
1601 if(i->data.size() - i->Offset < 3)
1603 i->Offset = i->data.size();
1604 i++;
1605 continue;
1608 ALubyte event = i->data[i->Offset++];
1609 ALubyte parm1, parm2;
1610 if(!(event&0x80))
1612 event = i->LastEvent;
1613 i->Offset--;
1615 if((event&MIDI_EVENT_MASK) != MIDI_SPECIAL)
1616 i->LastEvent = event;
1617 parm1 = i->data[i->Offset];
1618 parm2 = i->data[i->Offset+1];
1620 int channel = event&MIDI_CHANNEL_MASK;
1621 switch(event&MIDI_EVENT_MASK)
1623 case MIDI_NOTEOFF:
1624 pfluid_synth_noteoff(fluidSynth, channel, parm1);
1625 i->Offset += 2;
1626 break;
1627 case MIDI_NOTEON:
1628 pfluid_synth_noteon(fluidSynth, channel, parm1, parm2);
1629 i->Offset += 2;
1630 break;
1631 case MIDI_POLYPRESS:
1632 i->Offset += 2;
1633 break;
1635 case MIDI_CTRLCHANGE:
1636 pfluid_synth_cc(fluidSynth, channel, parm1, parm2);
1637 i->Offset += 2;
1638 break;
1639 case MIDI_PRGMCHANGE:
1640 pfluid_synth_program_change(fluidSynth, channel, parm1);
1641 i->Offset += 1;
1642 break;
1644 case MIDI_CHANPRESS:
1645 pfluid_synth_channel_pressure(fluidSynth, channel, parm1);
1646 i->Offset += 1;
1647 break;
1649 case MIDI_PITCHBEND:
1650 pfluid_synth_pitch_bend(fluidSynth, channel, (parm1&0x7F) | ((parm2&0x7F)<<7));
1651 i->Offset += 2;
1652 break;
1654 case MIDI_SPECIAL:
1655 switch(event)
1657 case MIDI_SYSEX:
1658 case MIDI_SYSEXEND:
1660 unsigned long len = i->ReadVarLen();
1662 if(i->data.size() - i->Offset < len)
1664 i->Offset = i->data.size();
1665 break;
1668 if(len > 1 && i->data[len-1] == MIDI_SYSEXEND)
1670 char *data = reinterpret_cast<char*>(&i->data[i->Offset]);
1671 pfluid_synth_sysex(fluidSynth, data, len-1, NULL, NULL, NULL, false);
1673 i->Offset += len;
1674 break;
1677 case MIDI_SONGPOS:
1678 i->Offset += 2;
1679 break;
1681 case MIDI_SONGSEL:
1682 i->Offset += 1;
1683 break;
1685 case MIDI_META:
1687 ALubyte metatype = i->data[i->Offset++];
1688 unsigned long val = i->ReadVarLen();
1690 if(i->data.size() - i->Offset < val)
1692 i->Offset = i->data.size();
1693 break;
1696 if(metatype == MIDI_META_EOT)
1698 i->Offset = i->data.size();
1699 break;
1702 if(metatype == MIDI_META_TEMPO && val >= 3)
1704 newtempo = (i->data[i->Offset] << 16) |
1705 (i->data[i->Offset+1] << 8) |
1706 (i->data[i->Offset+2]);
1709 i->Offset += val;
1710 break;
1713 default:
1714 /* The rest of the special events don't have any
1715 * data bytes */
1716 break;
1718 break;
1720 default:
1721 /* Shouldn't ever get to here */
1722 break;
1725 unsigned long val = i->ReadVarLen();
1726 i->SamplesLeft += val * samplesPerTick;
1728 if(newtempo)
1729 UpdateTempo(newtempo);
1732 void UpdateTempo(ALuint tempo)
1734 ALdouble sampletickrate = sampleRate / (1000000. / tempo) / Divisions;
1736 for(std::vector<MidiTrack>::iterator i = Tracks.begin(),
1737 end = Tracks.end();i != end;i++)
1739 if(i->Offset >= i->data.size())
1740 continue;
1741 i->SamplesLeft = i->SamplesLeft / samplesPerTick * sampletickrate;
1743 samplesPerTick = sampletickrate;
1746 void SetupSynth()
1748 fluidSettings = pnew_fluid_settings();
1749 if(fluidSettings)
1751 pfluid_settings_setnum(fluidSettings, "synth.gain", 0.5);
1752 pfluid_settings_setstr(fluidSettings, "synth.reverb.active", "yes");
1753 pfluid_settings_setstr(fluidSettings, "synth.chorus.active", "yes");
1754 pfluid_settings_setint(fluidSettings, "synth.polyphony", 256);
1755 pfluid_settings_setnum(fluidSettings, "synth.sample-rate", (double)sampleRate);
1757 fluidSynth = pnew_fluid_synth(fluidSettings);
1758 if(fluidSynth)
1760 const char *soundfont = getenv("FLUID_SOUNDFONT");
1761 if((fontID=pfluid_synth_sfload(fluidSynth, soundfont, true)) == FLUID_FAILED)
1763 pdelete_fluid_synth(fluidSynth);
1764 fluidSynth = NULL;
1770 #else
1771 struct fluidStream : public nullStream {
1772 fluidStream(std::istream*){}
1774 #endif
1777 template <typename T>
1778 alureStream *get_stream_decoder(const T &fdata)
1780 alureStream *stream;
1782 std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.begin();
1783 while(i != InstalledCallbacks.end() && i->first < 0)
1785 stream = new customStream(fdata, i->second);
1786 if(stream->IsValid())
1787 return stream;
1788 delete stream;
1789 i++;
1792 std::istream *file = new InStream(fdata);
1793 if(!file->fail())
1795 stream = new wavStream(file);
1796 if(stream->IsValid())
1797 return stream;
1798 delete stream;
1800 file->clear();
1801 file->seekg(0, std::ios_base::beg);
1802 stream = new aiffStream(file);
1803 if(stream->IsValid())
1804 return stream;
1805 delete stream;
1807 // Try libVorbisFile
1808 file->clear();
1809 file->seekg(0, std::ios_base::beg);
1810 stream = new oggStream(file);
1811 if(stream->IsValid())
1812 return stream;
1813 delete stream;
1815 // Try libFLAC
1816 file->clear();
1817 file->seekg(0, std::ios_base::beg);
1818 stream = new flacStream(file);
1819 if(stream->IsValid())
1820 return stream;
1821 delete stream;
1823 // Try FluidSynth
1824 file->clear();
1825 file->seekg(0, std::ios_base::beg);
1826 stream = new fluidStream(file);
1827 if(stream->IsValid())
1828 return stream;
1829 delete stream;
1831 // Try DUMB
1832 file->clear();
1833 file->seekg(0, std::ios_base::beg);
1834 stream = new dumbStream(file);
1835 if(stream->IsValid())
1836 return stream;
1837 delete stream;
1839 // Try libSndFile
1840 file->clear();
1841 file->seekg(0, std::ios_base::beg);
1842 stream = new sndStream(file);
1843 if(stream->IsValid())
1844 return stream;
1845 delete stream;
1847 // Try MPG123
1848 file->clear();
1849 file->seekg(0, std::ios_base::beg);
1850 stream = new mp3Stream(file);
1851 if(stream->IsValid())
1852 return stream;
1853 delete stream;
1855 SetError("Unsupported type");
1856 delete file;
1858 else
1860 SetError("Failed to open file");
1861 delete file;
1864 while(i != InstalledCallbacks.end())
1866 stream = new customStream(fdata, i->second);
1867 if(stream->IsValid())
1868 return stream;
1869 delete stream;
1870 i++;
1873 return new nullStream;
1876 alureStream *create_stream(const char *fname)
1877 { return get_stream_decoder(fname); }
1878 alureStream *create_stream(const MemDataInfo &memData)
1879 { return get_stream_decoder(memData); }
1881 alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb)
1882 { return new customStream(userdata, format, rate, cb); }