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