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