3D Audio GSoC:
[blender.git] / intern / audaspace / intern / AUD_C-API.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * Copyright 2009-2011 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * Audaspace is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Audaspace; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file audaspace/intern/AUD_C-API.cpp
28  *  \ingroup audaspaceintern
29  */
30
31
32 // needed for INT64_C
33 #ifndef __STDC_CONSTANT_MACROS
34 #define __STDC_CONSTANT_MACROS
35 #endif
36
37 #ifdef WITH_PYTHON
38 #include "AUD_PyInit.h"
39 #include "AUD_PyAPI.h"
40 #endif
41
42 #include <cstdlib>
43 #include <cstring>
44 #include <cmath>
45
46 #include "AUD_NULLDevice.h"
47 #include "AUD_I3DDevice.h"
48 #include "AUD_I3DHandle.h"
49 #include "AUD_FileFactory.h"
50 #include "AUD_StreamBufferFactory.h"
51 #include "AUD_DelayFactory.h"
52 #include "AUD_LimiterFactory.h"
53 #include "AUD_PingPongFactory.h"
54 #include "AUD_LoopFactory.h"
55 #include "AUD_RectifyFactory.h"
56 #include "AUD_EnvelopeFactory.h"
57 #include "AUD_LinearResampleFactory.h"
58 #include "AUD_LowpassFactory.h"
59 #include "AUD_HighpassFactory.h"
60 #include "AUD_AccumulatorFactory.h"
61 #include "AUD_SumFactory.h"
62 #include "AUD_SquareFactory.h"
63 #include "AUD_ChannelMapperFactory.h"
64 #include "AUD_Buffer.h"
65 #include "AUD_ReadDevice.h"
66 #include "AUD_IReader.h"
67 #include "AUD_SequencerFactory.h"
68 #include "AUD_SilenceFactory.h"
69
70 #ifdef WITH_SDL
71 #include "AUD_SDLDevice.h"
72 #endif
73
74 #ifdef WITH_OPENAL
75 #include "AUD_OpenALDevice.h"
76 #endif
77
78 #ifdef WITH_JACK
79 #include "AUD_JackDevice.h"
80 #endif
81
82
83 #ifdef WITH_FFMPEG
84 extern "C" {
85 #include <libavformat/avformat.h>
86 }
87 #endif
88
89 #include <cassert>
90
91 typedef AUD_Reference<AUD_IFactory> AUD_Sound;
92 typedef AUD_Reference<AUD_ReadDevice> AUD_Device;
93 typedef AUD_Reference<AUD_IHandle> AUD_Channel;
94 typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry;
95
96 #define AUD_CAPI_IMPLEMENTATION
97 #include "AUD_C-API.h"
98
99 #ifndef NULL
100 #define NULL 0
101 #endif
102
103 static AUD_Reference<AUD_IDevice> AUD_device;
104 static AUD_I3DDevice* AUD_3ddevice;
105
106 void AUD_initOnce()
107 {
108 #ifdef WITH_FFMPEG
109         av_register_all();
110 #endif
111 }
112
113 int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
114 {
115         AUD_Reference<AUD_IDevice> dev = NULL;
116
117         if(!AUD_device.isNull())
118                 AUD_exit();
119
120         try
121         {
122                 switch(device)
123                 {
124                 case AUD_NULL_DEVICE:
125                         dev = new AUD_NULLDevice();
126                         break;
127 #ifdef WITH_SDL
128                 case AUD_SDL_DEVICE:
129                         dev = new AUD_SDLDevice(specs, buffersize);
130                         break;
131 #endif
132 #ifdef WITH_OPENAL
133                 case AUD_OPENAL_DEVICE:
134                         dev = new AUD_OpenALDevice(specs, buffersize);
135                         break;
136 #endif
137 #ifdef WITH_JACK
138                 case AUD_JACK_DEVICE:
139                         dev = new AUD_JackDevice("Blender", specs, buffersize);
140                         break;
141 #endif
142                 default:
143                         return false;
144                 }
145
146                 AUD_device = dev;
147                 AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device.get());
148
149                 return true;
150         }
151         catch(AUD_Exception&)
152         {
153                 return false;
154         }
155 }
156
157 void AUD_exit()
158 {
159         AUD_device = NULL;
160         AUD_3ddevice = NULL;
161 }
162
163 #ifdef WITH_PYTHON
164 static PyObject* AUD_getCDevice(PyObject* self)
165 {
166         if(!AUD_device.isNull())
167         {
168                 Device* device = (Device*)Device_empty();
169                 if(device != NULL)
170                 {
171                         device->device = new AUD_Reference<AUD_IDevice>(AUD_device);
172                         return (PyObject*)device;
173                 }
174         }
175
176         Py_RETURN_NONE;
177 }
178
179 static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS,
180                                                                                   "device()\n\n"
181                                                                                   "Returns the application's :class:`Device`.\n\n"
182                                                                                   ":return: The application's :class:`Device`.\n"
183                                                                                   ":rtype: :class:`Device`"}};
184
185 extern "C" {
186 extern void* sound_get_factory(void* sound);
187 }
188
189 static PyObject* AUD_getSoundFromPointer(PyObject* self, PyObject* args)
190 {
191         long int lptr;
192
193         if(PyArg_Parse(args, "l:_sound_from_pointer", &lptr))
194         {
195                 if(lptr)
196                 {
197                         AUD_Reference<AUD_IFactory>* factory = (AUD_Reference<AUD_IFactory>*) sound_get_factory((void*) lptr);
198
199                         if(factory)
200                         {
201                                 Factory* obj = (Factory*) Factory_empty();
202                                 if(obj)
203                                 {
204                                         obj->factory = new AUD_Reference<AUD_IFactory>(*factory);
205                                         return (PyObject*) obj;
206                                 }
207                         }
208                 }
209         }
210
211         Py_RETURN_NONE;
212 }
213
214 static PyMethodDef meth_sound_from_pointer[] = {{ "_sound_from_pointer", (PyCFunction)AUD_getSoundFromPointer, METH_O,
215                                                                                   "_sound_from_pointer(pointer)\n\n"
216                                                                                   "Returns the corresponding :class:`Factory` object.\n\n"
217                                                                                   ":arg pointer: The pointer to the bSound object as long.\n"
218                                                                                   ":type pointer: long\n"
219                                                                                   ":return: The corresponding :class:`Factory` object.\n"
220                                                                                   ":rtype: :class:`Factory`"}};
221
222 PyObject* AUD_initPython()
223 {
224         PyObject* module = PyInit_aud();
225         PyModule_AddObject(module, "device", (PyObject*)PyCFunction_New(meth_getcdevice, NULL));
226         PyModule_AddObject(module, "_sound_from_pointer", (PyObject*)PyCFunction_New(meth_sound_from_pointer, NULL));
227         PyDict_SetItemString(PyImport_GetModuleDict(), "aud", module);
228
229         return module;
230 }
231
232 PyObject* AUD_getPythonFactory(AUD_Sound* sound)
233 {
234         if(sound)
235         {
236                 Factory* obj = (Factory*) Factory_empty();
237                 if(obj)
238                 {
239                         obj->factory = new AUD_Reference<AUD_IFactory>(*sound);
240                         return (PyObject*) obj;
241                 }
242         }
243
244         return NULL;
245 }
246
247 AUD_Sound* AUD_getPythonSound(PyObject* sound)
248 {
249         Factory* factory = checkFactory(sound);
250
251         if(!factory)
252                 return NULL;
253
254         return new AUD_Reference<AUD_IFactory>(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(factory->factory));
255 }
256
257 #endif
258
259 void AUD_lock()
260 {
261         AUD_device->lock();
262 }
263
264 void AUD_unlock()
265 {
266         AUD_device->unlock();
267 }
268
269 AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
270 {
271         assert(sound);
272
273         AUD_SoundInfo info;
274         info.specs.channels = AUD_CHANNELS_INVALID;
275         info.specs.rate = AUD_RATE_INVALID;
276         info.length = 0.0f;
277
278         try
279         {
280                 AUD_Reference<AUD_IReader> reader = (*sound)->createReader();
281
282                 if(!reader.isNull())
283                 {
284                         info.specs = reader->getSpecs();
285                         info.length = reader->getLength() / (float) info.specs.rate;
286                 }
287         }
288         catch(AUD_Exception&)
289         {
290         }
291
292         return info;
293 }
294
295 AUD_Sound* AUD_load(const char* filename)
296 {
297         assert(filename);
298         return new AUD_Sound(new AUD_FileFactory(filename));
299 }
300
301 AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size)
302 {
303         assert(buffer);
304         return new AUD_Sound(new AUD_FileFactory(buffer, size));
305 }
306
307 AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
308 {
309         assert(sound);
310
311         try
312         {
313                 return new AUD_Sound(new AUD_StreamBufferFactory(*sound));
314         }
315         catch(AUD_Exception&)
316         {
317                 return NULL;
318         }
319 }
320
321 AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
322 {
323         assert(sound);
324
325         try
326         {
327                 return new AUD_Sound(new AUD_DelayFactory(*sound, delay));
328         }
329         catch(AUD_Exception&)
330         {
331                 return NULL;
332         }
333 }
334
335 AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
336 {
337         assert(sound);
338
339         try
340         {
341                 return new AUD_Sound(new AUD_LimiterFactory(*sound, start, end));
342         }
343         catch(AUD_Exception&)
344         {
345                 return NULL;
346         }
347 }
348
349 AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
350 {
351         assert(sound);
352
353         try
354         {
355                 return new AUD_Sound(new AUD_PingPongFactory(*sound));
356         }
357         catch(AUD_Exception&)
358         {
359                 return NULL;
360         }
361 }
362
363 AUD_Sound* AUD_loopSound(AUD_Sound* sound)
364 {
365         assert(sound);
366
367         try
368         {
369                 return new AUD_Sound(new AUD_LoopFactory(*sound));
370         }
371         catch(AUD_Exception&)
372         {
373                 return NULL;
374         }
375 }
376
377 int AUD_setLoop(AUD_Channel* handle, int loops)
378 {
379         assert(handle);
380
381         try
382         {
383                 return (*handle)->setLoopCount(loops);
384         }
385         catch(AUD_Exception&)
386         {
387         }
388
389         return false;
390 }
391
392 AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
393 {
394         assert(sound);
395
396         try
397         {
398                 return new AUD_Sound(new AUD_RectifyFactory(*sound));
399         }
400         catch(AUD_Exception&)
401         {
402                 return NULL;
403         }
404 }
405
406 void AUD_unload(AUD_Sound* sound)
407 {
408         assert(sound);
409         delete sound;
410 }
411
412 AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
413 {
414         assert(sound);
415         try
416         {
417                 AUD_Channel channel = AUD_device->play(*sound, keep);
418                 if(!channel.isNull())
419                         return new AUD_Channel(channel);
420         }
421         catch(AUD_Exception&)
422         {
423         }
424         return NULL;
425 }
426
427 int AUD_pause(AUD_Channel* handle)
428 {
429         assert(handle);
430         return (*handle)->pause();
431 }
432
433 int AUD_resume(AUD_Channel* handle)
434 {
435         assert(handle);
436         return (*handle)->resume();
437 }
438
439 int AUD_stop(AUD_Channel* handle)
440 {
441         assert(handle);
442         int result = (*handle)->stop();
443         delete handle;
444         return result;
445 }
446
447 int AUD_setKeep(AUD_Channel* handle, int keep)
448 {
449         assert(handle);
450         return (*handle)->setKeep(keep);
451 }
452
453 int AUD_seek(AUD_Channel* handle, float seekTo)
454 {
455         assert(handle);
456         return (*handle)->seek(seekTo);
457 }
458
459 float AUD_getPosition(AUD_Channel* handle)
460 {
461         assert(handle);
462         return (*handle)->getPosition();
463 }
464
465 AUD_Status AUD_getStatus(AUD_Channel* handle)
466 {
467         assert(handle);
468         return (*handle)->getStatus();
469 }
470
471 int AUD_setListenerLocation(const float* location)
472 {
473         if(AUD_3ddevice)
474         {
475                 AUD_Vector3 v(location[0], location[1], location[2]);
476                 AUD_3ddevice->setListenerLocation(v);
477                 return true;
478         }
479
480         return false;
481 }
482
483 int AUD_setListenerVelocity(const float* velocity)
484 {
485         if(AUD_3ddevice)
486         {
487                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
488                 AUD_3ddevice->setListenerVelocity(v);
489                 return true;
490         }
491
492         return false;
493 }
494
495 int AUD_setListenerOrientation(const float* orientation)
496 {
497         if(AUD_3ddevice)
498         {
499                 AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]);
500                 AUD_3ddevice->setListenerOrientation(q);
501                 return true;
502         }
503
504         return false;
505 }
506
507 int AUD_setSpeedOfSound(float speed)
508 {
509         if(AUD_3ddevice)
510         {
511                 AUD_3ddevice->setSpeedOfSound(speed);
512                 return true;
513         }
514
515         return false;
516 }
517
518 int AUD_setDopplerFactor(float factor)
519 {
520         if(AUD_3ddevice)
521         {
522                 AUD_3ddevice->setDopplerFactor(factor);
523                 return true;
524         }
525
526         return false;
527 }
528
529 int AUD_setDistanceModel(AUD_DistanceModel model)
530 {
531         if(AUD_3ddevice)
532         {
533                 AUD_3ddevice->setDistanceModel(model);
534                 return true;
535         }
536
537         return false;
538 }
539
540 int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
541 {
542         assert(handle);
543         AUD_Reference<AUD_I3DHandle> h(*handle);
544
545         if(!h.isNull())
546         {
547                 AUD_Vector3 v(location[0], location[1], location[2]);
548                 return h->setSourceLocation(v);
549         }
550
551         return false;
552 }
553
554 int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
555 {
556         assert(handle);
557         AUD_Reference<AUD_I3DHandle> h(*handle);
558
559         if(!h.isNull())
560         {
561                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
562                 return h->setSourceVelocity(v);
563         }
564
565         return false;
566 }
567
568 int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
569 {
570         assert(handle);
571         AUD_Reference<AUD_I3DHandle> h(*handle);
572
573         if(!h.isNull())
574         {
575                 AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]);
576                 return h->setSourceOrientation(q);
577         }
578
579         return false;
580 }
581
582 int AUD_setRelative(AUD_Channel* handle, int relative)
583 {
584         assert(handle);
585         AUD_Reference<AUD_I3DHandle> h(*handle);
586
587         if(!h.isNull())
588         {
589                 return h->setRelative(relative);
590         }
591
592         return false;
593 }
594
595 int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
596 {
597         assert(handle);
598         AUD_Reference<AUD_I3DHandle> h(*handle);
599
600         if(!h.isNull())
601         {
602                 return h->setVolumeMaximum(volume);
603         }
604
605         return false;
606 }
607
608 int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
609 {
610         assert(handle);
611         AUD_Reference<AUD_I3DHandle> h(*handle);
612
613         if(!h.isNull())
614         {
615                 return h->setVolumeMinimum(volume);
616         }
617
618         return false;
619 }
620
621 int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
622 {
623         assert(handle);
624         AUD_Reference<AUD_I3DHandle> h(*handle);
625
626         if(!h.isNull())
627         {
628                 return h->setDistanceMaximum(distance);
629         }
630
631         return false;
632 }
633
634 int AUD_setDistanceReference(AUD_Channel* handle, float distance)
635 {
636         assert(handle);
637         AUD_Reference<AUD_I3DHandle> h(*handle);
638
639         if(!h.isNull())
640         {
641                 return h->setDistanceReference(distance);
642         }
643
644         return false;
645 }
646
647 int AUD_setAttenuation(AUD_Channel* handle, float factor)
648 {
649         assert(handle);
650         AUD_Reference<AUD_I3DHandle> h(*handle);
651
652         if(!h.isNull())
653         {
654                 return h->setAttenuation(factor);
655         }
656
657         return false;
658 }
659
660 int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
661 {
662         assert(handle);
663         AUD_Reference<AUD_I3DHandle> h(*handle);
664
665         if(!h.isNull())
666         {
667                 return h->setConeAngleOuter(angle);
668         }
669
670         return false;
671 }
672
673 int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
674 {
675         assert(handle);
676         AUD_Reference<AUD_I3DHandle> h(*handle);
677
678         if(!h.isNull())
679         {
680                 return h->setConeAngleInner(angle);
681         }
682
683         return false;
684 }
685
686 int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
687 {
688         assert(handle);
689         AUD_Reference<AUD_I3DHandle> h(*handle);
690
691         if(!h.isNull())
692         {
693                 return h->setConeVolumeOuter(volume);
694         }
695
696         return false;
697 }
698
699 int AUD_setSoundVolume(AUD_Channel* handle, float volume)
700 {
701         assert(handle);
702         try
703         {
704                 return (*handle)->setVolume(volume);
705         }
706         catch(AUD_Exception&) {}
707         return false;
708 }
709
710 int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
711 {
712         assert(handle);
713         try
714         {
715                 return (*handle)->setPitch(pitch);
716         }
717         catch(AUD_Exception&) {}
718         return false;
719 }
720
721 AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
722 {
723         try
724         {
725                 return new AUD_Device(new AUD_ReadDevice(specs));
726         }
727         catch(AUD_Exception&)
728         {
729                 return NULL;
730         }
731 }
732
733 AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
734 {
735         assert(device);
736         assert(sound);
737
738         try
739         {
740                 AUD_Channel channel = (*device)->play(*sound);
741                 if(!channel.isNull())
742                 {
743                         channel->seek(seek);
744                         return new AUD_Channel(channel);
745                 }
746         }
747         catch(AUD_Exception&)
748         {
749         }
750         return NULL;
751 }
752
753 int AUD_setDeviceVolume(AUD_Device* device, float volume)
754 {
755         assert(device);
756
757         try
758         {
759                 (*device)->setVolume(volume);
760                 return true;
761         }
762         catch(AUD_Exception&) {}
763
764         return false;
765 }
766
767 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
768 {
769         assert(device);
770         assert(buffer);
771
772         try
773         {
774                 return (*device)->read(buffer, length);
775         }
776         catch(AUD_Exception&)
777         {
778                 return false;
779         }
780 }
781
782 void AUD_closeReadDevice(AUD_Device* device)
783 {
784         assert(device);
785
786         try
787         {
788                 delete device;
789         }
790         catch(AUD_Exception&)
791         {
792         }
793 }
794
795 float* AUD_readSoundBuffer(const char* filename, float low, float high,
796                                                    float attack, float release, float threshold,
797                                                    int accumulate, int additive, int square,
798                                                    float sthreshold, int samplerate, int* length)
799 {
800         AUD_Buffer buffer;
801         AUD_DeviceSpecs specs;
802         specs.channels = AUD_CHANNELS_MONO;
803         specs.rate = (AUD_SampleRate)samplerate;
804         AUD_Reference<AUD_IFactory> sound;
805
806         AUD_Reference<AUD_IFactory> file = new AUD_FileFactory(filename);
807
808         AUD_Reference<AUD_IReader> reader = file->createReader();
809         AUD_SampleRate rate = reader->getSpecs().rate;
810
811         sound = new AUD_ChannelMapperFactory(file, specs);
812
813         if(high < rate)
814                 sound = new AUD_LowpassFactory(sound, high);
815         if(low > 0)
816                 sound = new AUD_HighpassFactory(sound, low);;
817
818         sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f);
819         sound = new AUD_LinearResampleFactory(sound, specs);
820
821         if(square)
822                 sound = new AUD_SquareFactory(sound, sthreshold);
823
824         if(accumulate)
825                 sound = new AUD_AccumulatorFactory(sound, additive);
826         else if(additive)
827                 sound = new AUD_SumFactory(sound);
828
829         reader = sound->createReader();
830
831         if(reader.isNull())
832                 return NULL;
833
834         int len;
835         int position = 0;
836         bool eos;
837         do
838         {
839                 len = samplerate;
840                 buffer.resize((position + len) * sizeof(float), true);
841                 reader->read(len, eos, buffer.getBuffer() + position);
842                 position += len;
843         } while(!eos);
844
845         float* result = (float*)malloc(position * sizeof(float));
846         memcpy(result, buffer.getBuffer(), position * sizeof(float));
847         *length = position;
848         return result;
849 }
850
851 static void pauseSound(AUD_Channel* handle)
852 {
853         assert(handle);
854         (*handle)->pause();
855 }
856
857 AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
858 {
859         AUD_Reference<AUD_IFactory> silence = new AUD_SilenceFactory;
860         AUD_Reference<AUD_IFactory> limiter = new AUD_LimiterFactory(silence, 0, seconds);
861
862         AUD_device->lock();
863
864         try
865         {
866                 AUD_Channel channel = AUD_device->play(limiter);
867                 if(!channel.isNull())
868                 {
869                         channel->setStopCallback((stopCallback)pauseSound, handle);
870                         AUD_device->unlock();
871                         return new AUD_Channel(channel);
872                 }
873         }
874         catch(AUD_Exception&)
875         {
876         }
877
878         AUD_device->unlock();
879
880         return NULL;
881 }
882
883 AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume)
884 {
885 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
886  * is initialized.
887
888         return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
889 */
890         AUD_Specs specs;
891         specs.channels = AUD_CHANNELS_STEREO;
892         specs.rate = AUD_RATE_44100;
893         AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume));
894         (*sequencer)->setThis(sequencer);
895         return reinterpret_cast<AUD_Sound*>(sequencer);
896 }
897
898 void AUD_destroySequencer(AUD_Sound* sequencer)
899 {
900         delete sequencer;
901 }
902
903 void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted)
904 {
905         ((AUD_SequencerFactory*)sequencer->get())->mute(muted);
906 }
907
908 AUD_Reference<AUD_SequencerEntry>* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound,
909                                                                  float begin, float end, float skip, void* data)
910 {
911         return new AUD_Reference<AUD_SequencerEntry>(((AUD_SequencerFactory*)sequencer->get())->add(sound, begin, end, skip, data));
912 }
913
914 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry)
915 {
916         ((AUD_SequencerFactory*)sequencer->get())->remove(*entry);
917         delete entry;
918 }
919
920 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry,
921                                    float begin, float end, float skip)
922 {
923         ((AUD_SequencerFactory*)sequencer->get())->move(*entry, begin, end, skip);
924 }
925
926 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, char mute)
927 {
928         ((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute);
929 }
930
931 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
932 {
933         AUD_DeviceSpecs specs;
934         sample_t* buf;
935         AUD_Buffer aBuffer;
936
937         specs.rate = AUD_RATE_INVALID;
938         specs.channels = AUD_CHANNELS_MONO;
939         specs.format = AUD_FORMAT_INVALID;
940
941         AUD_Reference<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader();
942
943         int len = reader->getLength();
944         float samplejump = (float)len / (float)length;
945         float min, max;
946         bool eos;
947
948         for(int i = 0; i < length; i++)
949         {
950                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
951
952                 if(aBuffer.getSize() < len * AUD_SAMPLE_SIZE(reader->getSpecs()))
953                 {
954                         aBuffer.resize(len * AUD_SAMPLE_SIZE(reader->getSpecs()));
955                         buf = aBuffer.getBuffer();
956                 }
957
958                 reader->read(len, eos, buf);
959
960                 if(eos)
961                 {
962                         length = i;
963                         break;
964                 }
965
966                 max = min = *buf;
967                 for(int j = 1; j < len; j++)
968                 {
969                         if(buf[j] < min)
970                                 min = buf[j];
971                         if(buf[j] > max)
972                                 max = buf[j];
973                         buffer[i * 2] = min;
974                         buffer[i * 2 + 1] = max;
975                 }
976         }
977
978         return length;
979 }
980
981 void AUD_startPlayback()
982 {
983 #ifdef WITH_JACK
984         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
985         if(device)
986                 device->startPlayback();
987 #endif
988 }
989
990 void AUD_stopPlayback()
991 {
992 #ifdef WITH_JACK
993         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
994         if(device)
995                 device->stopPlayback();
996 #endif
997 }
998
999 void AUD_seekSequencer(AUD_Channel* handle, float time)
1000 {
1001 #ifdef WITH_JACK
1002         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1003         if(device)
1004                 device->seekPlayback(time);
1005         else
1006 #endif
1007         {
1008                 assert(handle);
1009                 (*handle)->seek(time);
1010         }
1011 }
1012
1013 float AUD_getSequencerPosition(AUD_Channel* handle)
1014 {
1015 #ifdef WITH_JACK
1016         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1017         if(device)
1018                 return device->getPlaybackPosition();
1019         else
1020 #endif
1021         {
1022                 assert(handle);
1023                 return (*handle)->getPosition();
1024         }
1025 }
1026
1027 #ifdef WITH_JACK
1028 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
1029 {
1030         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1031         if(device)
1032                 device->setSyncCallback(function, data);
1033 }
1034 #endif
1035
1036 int AUD_doesPlayback()
1037 {
1038 #ifdef WITH_JACK
1039         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1040         if(device)
1041                 return device->doesPlayback();
1042 #endif
1043         return -1;
1044 }
1045
1046 AUD_Sound* AUD_copy(AUD_Sound* sound)
1047 {
1048         return new AUD_Reference<AUD_IFactory>(*sound);
1049 }
1050
1051 void AUD_freeChannel(AUD_Channel* channel)
1052 {
1053         delete channel;
1054 }