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