db76b9b4fafff22b85584bb2759c082188c80ae3
[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_Handle;
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_Handle* 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_Handle* AUD_play(AUD_Sound* sound, int keep)
413 {
414         assert(sound);
415         try
416         {
417                 AUD_Handle handle = AUD_device->play(*sound, keep);
418                 if(!handle.isNull())
419                         return new AUD_Handle(handle);
420         }
421         catch(AUD_Exception&)
422         {
423         }
424         return NULL;
425 }
426
427 int AUD_pause(AUD_Handle* handle)
428 {
429         assert(handle);
430         return (*handle)->pause();
431 }
432
433 int AUD_resume(AUD_Handle* handle)
434 {
435         assert(handle);
436         return (*handle)->resume();
437 }
438
439 int AUD_stop(AUD_Handle* handle)
440 {
441         assert(handle);
442         int result = (*handle)->stop();
443         delete handle;
444         return result;
445 }
446
447 int AUD_setKeep(AUD_Handle* handle, int keep)
448 {
449         assert(handle);
450         return (*handle)->setKeep(keep);
451 }
452
453 int AUD_seek(AUD_Handle* handle, float seekTo)
454 {
455         assert(handle);
456         return (*handle)->seek(seekTo);
457 }
458
459 float AUD_getPosition(AUD_Handle* handle)
460 {
461         assert(handle);
462         return (*handle)->getPosition();
463 }
464
465 AUD_Status AUD_getStatus(AUD_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* 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_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
734 {
735         assert(device);
736         assert(sound);
737
738         try
739         {
740                 AUD_Handle handle = (*device)->play(*sound);
741                 if(!handle.isNull())
742                 {
743                         handle->seek(seek);
744                         return new AUD_Handle(handle);
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, double 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_Handle* handle)
852 {
853         assert(handle);
854         (*handle)->pause();
855 }
856
857 AUD_Handle* AUD_pauseAfter(AUD_Handle* 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_Handle handle2 = AUD_device->play(limiter);
867                 if(!handle2.isNull())
868                 {
869                         handle2->setStopCallback((stopCallback)pauseSound, handle);
870                         AUD_device->unlock();
871                         return new AUD_Handle(handle2);
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         // specs are changed at a later point!
886         AUD_Specs specs;
887         specs.channels = AUD_CHANNELS_STEREO;
888         specs.rate = AUD_RATE_44100;
889         AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume));
890         return reinterpret_cast<AUD_Sound*>(sequencer);
891 }
892
893 void AUD_destroySequencer(AUD_Sound* sequencer)
894 {
895         delete sequencer;
896 }
897
898 void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted)
899 {
900         ((AUD_SequencerFactory*)sequencer->get())->mute(muted);
901 }
902
903 AUD_Reference<AUD_SequencerEntry>* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound,
904                                                                  float begin, float end, float skip, void* data)
905 {
906         return new AUD_Reference<AUD_SequencerEntry>(((AUD_SequencerFactory*)sequencer->get())->add(sound, begin, end, skip, data));
907 }
908
909 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry)
910 {
911         ((AUD_SequencerFactory*)sequencer->get())->remove(*entry);
912         delete entry;
913 }
914
915 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry,
916                                    float begin, float end, float skip)
917 {
918         ((AUD_SequencerFactory*)sequencer->get())->move(*entry, begin, end, skip);
919 }
920
921 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, char mute)
922 {
923         ((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute);
924 }
925
926 void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer)
927 {
928         ((AUD_SequencerFactory*)sequencer->get())->setSpecs(AUD_device->getSpecs().specs);
929 }
930
931 void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs)
932 {
933         ((AUD_SequencerFactory*)sequencer->get())->setSpecs(specs);
934 }
935
936 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
937 {
938         AUD_DeviceSpecs specs;
939         sample_t* buf;
940         AUD_Buffer aBuffer;
941
942         specs.rate = AUD_RATE_INVALID;
943         specs.channels = AUD_CHANNELS_MONO;
944         specs.format = AUD_FORMAT_INVALID;
945
946         AUD_Reference<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader();
947
948         int len = reader->getLength();
949         float samplejump = (float)len / (float)length;
950         float min, max;
951         bool eos;
952
953         for(int i = 0; i < length; i++)
954         {
955                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
956
957                 if(aBuffer.getSize() < len * AUD_SAMPLE_SIZE(reader->getSpecs()))
958                 {
959                         aBuffer.resize(len * AUD_SAMPLE_SIZE(reader->getSpecs()));
960                         buf = aBuffer.getBuffer();
961                 }
962
963                 reader->read(len, eos, buf);
964
965                 if(eos)
966                 {
967                         length = i;
968                         break;
969                 }
970
971                 max = min = *buf;
972                 for(int j = 1; j < len; j++)
973                 {
974                         if(buf[j] < min)
975                                 min = buf[j];
976                         if(buf[j] > max)
977                                 max = buf[j];
978                         buffer[i * 2] = min;
979                         buffer[i * 2 + 1] = max;
980                 }
981         }
982
983         return length;
984 }
985
986 void AUD_startPlayback()
987 {
988 #ifdef WITH_JACK
989         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
990         if(device)
991                 device->startPlayback();
992 #endif
993 }
994
995 void AUD_stopPlayback()
996 {
997 #ifdef WITH_JACK
998         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
999         if(device)
1000                 device->stopPlayback();
1001 #endif
1002 }
1003
1004 void AUD_seekSequencer(AUD_Handle* handle, float time)
1005 {
1006 #ifdef WITH_JACK
1007         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1008         if(device)
1009                 device->seekPlayback(time);
1010         else
1011 #endif
1012         {
1013                 assert(handle);
1014                 (*handle)->seek(time);
1015         }
1016 }
1017
1018 float AUD_getSequencerPosition(AUD_Handle* handle)
1019 {
1020 #ifdef WITH_JACK
1021         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1022         if(device)
1023                 return device->getPlaybackPosition();
1024         else
1025 #endif
1026         {
1027                 assert(handle);
1028                 return (*handle)->getPosition();
1029         }
1030 }
1031
1032 #ifdef WITH_JACK
1033 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
1034 {
1035         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1036         if(device)
1037                 device->setSyncCallback(function, data);
1038 }
1039 #endif
1040
1041 int AUD_doesPlayback()
1042 {
1043 #ifdef WITH_JACK
1044         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
1045         if(device)
1046                 return device->doesPlayback();
1047 #endif
1048         return -1;
1049 }
1050
1051 AUD_Sound* AUD_copy(AUD_Sound* sound)
1052 {
1053         return new AUD_Reference<AUD_IFactory>(*sound);
1054 }
1055
1056 void AUD_freeHandle(AUD_Handle* handle)
1057 {
1058         delete handle;
1059 }