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