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