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