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