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