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