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