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