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