8740f62c9a79a45fbb447b74a2a5d9dfbb6947fe
[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 #include <cstdlib>
27 #include <cstring>
28 #include <cmath>
29
30 #ifdef WITH_FFMPEG
31 // needed for INT64_C
32 #define __STDC_CONSTANT_MACROS
33 #endif
34
35 #include "AUD_NULLDevice.h"
36 #include "AUD_I3DDevice.h"
37 #include "AUD_FileFactory.h"
38 #include "AUD_StreamBufferFactory.h"
39 #include "AUD_DelayFactory.h"
40 #include "AUD_LimiterFactory.h"
41 #include "AUD_PingPongFactory.h"
42 #include "AUD_LoopFactory.h"
43 #include "AUD_RectifyFactory.h"
44 #include "AUD_EnvelopeFactory.h"
45 #include "AUD_LinearResampleFactory.h"
46 #include "AUD_LowpassFactory.h"
47 #include "AUD_HighpassFactory.h"
48 #include "AUD_AccumulatorFactory.h"
49 #include "AUD_SumFactory.h"
50 #include "AUD_SquareFactory.h"
51 #include "AUD_ChannelMapperFactory.h"
52 #include "AUD_Buffer.h"
53 #include "AUD_ReadDevice.h"
54 #include "AUD_SourceCaps.h"
55 #include "AUD_IReader.h"
56 #include "AUD_SequencerFactory.h"
57
58 #ifdef WITH_SDL
59 #include "AUD_SDLDevice.h"
60 #endif
61
62 #ifdef WITH_OPENAL
63 #include "AUD_OpenALDevice.h"
64 #endif
65
66 #ifdef WITH_JACK
67 #include "AUD_JackDevice.h"
68 #endif
69
70
71 #ifdef WITH_FFMPEG
72 extern "C" {
73 #include <libavformat/avformat.h>
74 }
75 #endif
76
77 #include <cassert>
78
79 typedef AUD_IFactory AUD_Sound;
80 typedef AUD_ReadDevice AUD_Device;
81
82 #define AUD_CAPI_IMPLEMENTATION
83 #include "AUD_C-API.h"
84
85 #ifndef NULL
86 #define NULL 0
87 #endif
88
89 static AUD_IDevice* AUD_device = NULL;
90 static int AUD_available_devices[4];
91 static AUD_I3DDevice* AUD_3ddevice = NULL;
92
93 void AUD_initOnce()
94 {
95 #ifdef WITH_FFMPEG
96         av_register_all();
97 #endif
98 }
99
100 int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
101 {
102         AUD_IDevice* dev = NULL;
103
104         if(AUD_device)
105                 AUD_exit();
106
107         try
108         {
109                 switch(device)
110                 {
111                 case AUD_NULL_DEVICE:
112                         dev = new AUD_NULLDevice();
113                         break;
114 #ifdef WITH_SDL
115                 case AUD_SDL_DEVICE:
116                         dev = new AUD_SDLDevice(specs, buffersize);
117                         break;
118 #endif
119 #ifdef WITH_OPENAL
120                 case AUD_OPENAL_DEVICE:
121                         dev = new AUD_OpenALDevice(specs, buffersize);
122                         break;
123 #endif
124 #ifdef WITH_JACK
125                 case AUD_JACK_DEVICE:
126                         dev = new AUD_JackDevice(specs, buffersize);
127                         break;
128 #endif
129                 default:
130                         return false;
131                 }
132
133                 AUD_device = dev;
134                 if(AUD_device->checkCapability(AUD_CAPS_3D_DEVICE))
135                         AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device);
136
137                 return true;
138         }
139         catch(AUD_Exception)
140         {
141                 return false;
142         }
143 }
144
145 int* AUD_enumDevices()
146 {
147         int i = 0;
148 #ifdef WITH_SDL
149         AUD_available_devices[i++] = AUD_SDL_DEVICE;
150 #endif
151 #ifdef WITH_OPENAL
152         AUD_available_devices[i++] = AUD_OPENAL_DEVICE;
153 #endif
154 #ifdef WITH_JACK
155         AUD_available_devices[i++] = AUD_JACK_DEVICE;
156 #endif
157         AUD_available_devices[i++] = AUD_NULL_DEVICE;
158         return AUD_available_devices;
159 }
160
161 void AUD_exit()
162 {
163         if(AUD_device)
164         {
165                 delete AUD_device;
166                 AUD_device = NULL;
167                 AUD_3ddevice = NULL;
168         }
169 }
170
171 void AUD_lock()
172 {
173         assert(AUD_device);
174         AUD_device->lock();
175 }
176
177 void AUD_unlock()
178 {
179         assert(AUD_device);
180         AUD_device->unlock();
181 }
182
183 AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
184 {
185         assert(sound);
186
187         AUD_IReader* reader = sound->createReader();
188
189         AUD_SoundInfo info;
190
191         if(reader)
192         {
193                 info.specs = reader->getSpecs();
194                 info.length = reader->getLength() / (float) info.specs.rate;
195         }
196         else
197         {
198                 info.specs.channels = AUD_CHANNELS_INVALID;
199                 info.specs.rate = AUD_RATE_INVALID;
200                 info.length = 0.0f;
201         }
202
203         return info;
204 }
205
206 AUD_Sound* AUD_load(const char* filename)
207 {
208         assert(filename);
209         return new AUD_FileFactory(filename);
210 }
211
212 AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size)
213 {
214         assert(buffer);
215         return new AUD_FileFactory(buffer, size);
216 }
217
218 AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
219 {
220         assert(sound);
221
222         try
223         {
224                 return new AUD_StreamBufferFactory(sound);
225         }
226         catch(AUD_Exception)
227         {
228                 return NULL;
229         }
230 }
231
232 AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
233 {
234         assert(sound);
235
236         try
237         {
238                 return new AUD_DelayFactory(sound, delay);
239         }
240         catch(AUD_Exception)
241         {
242                 return NULL;
243         }
244 }
245
246 AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
247 {
248         assert(sound);
249
250         try
251         {
252                 return new AUD_LimiterFactory(sound, start, end);
253         }
254         catch(AUD_Exception)
255         {
256                 return NULL;
257         }
258 }
259
260 AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
261 {
262         assert(sound);
263
264         try
265         {
266                 return new AUD_PingPongFactory(sound);
267         }
268         catch(AUD_Exception)
269         {
270                 return NULL;
271         }
272 }
273
274 AUD_Sound* AUD_loopSound(AUD_Sound* sound)
275 {
276         assert(sound);
277
278         try
279         {
280                 return new AUD_LoopFactory(sound);
281         }
282         catch(AUD_Exception)
283         {
284                 return NULL;
285         }
286 }
287
288 int AUD_setLoop(AUD_Handle* handle, int loops, float time)
289 {
290         if(handle)
291         {
292                 AUD_Message message;
293                 message.type = AUD_MSG_LOOP;
294                 message.loopcount = loops;
295                 message.time = time;
296
297                 try
298                 {
299                         return AUD_device->sendMessage(handle, message);
300                 }
301                 catch(AUD_Exception)
302                 {
303                 }
304         }
305         return false;
306 }
307
308 AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
309 {
310         assert(sound);
311
312         try
313         {
314                 return new AUD_RectifyFactory(sound);
315         }
316         catch(AUD_Exception)
317         {
318                 return NULL;
319         }
320 }
321
322 void AUD_unload(AUD_Sound* sound)
323 {
324         assert(sound);
325         delete sound;
326 }
327
328 AUD_Handle* AUD_play(AUD_Sound* sound, int keep)
329 {
330         assert(AUD_device);
331         assert(sound);
332         try
333         {
334                 return AUD_device->play(sound, keep);
335         }
336         catch(AUD_Exception)
337         {
338                 return NULL;
339         }
340 }
341
342 int AUD_pause(AUD_Handle* handle)
343 {
344         assert(AUD_device);
345         return AUD_device->pause(handle);
346 }
347
348 int AUD_resume(AUD_Handle* handle)
349 {
350         assert(AUD_device);
351         return AUD_device->resume(handle);
352 }
353
354 int AUD_stop(AUD_Handle* handle)
355 {
356         if(AUD_device)
357                 return AUD_device->stop(handle);
358         return false;
359 }
360
361 int AUD_setKeep(AUD_Handle* handle, int keep)
362 {
363         assert(AUD_device);
364         return AUD_device->setKeep(handle, keep);
365 }
366
367 int AUD_seek(AUD_Handle* handle, float seekTo)
368 {
369         assert(AUD_device);
370         return AUD_device->seek(handle, seekTo);
371 }
372
373 float AUD_getPosition(AUD_Handle* handle)
374 {
375         assert(AUD_device);
376         return AUD_device->getPosition(handle);
377 }
378
379 AUD_Status AUD_getStatus(AUD_Handle* handle)
380 {
381         assert(AUD_device);
382         return AUD_device->getStatus(handle);
383 }
384
385 AUD_Handle* AUD_play3D(AUD_Sound* sound, int keep)
386 {
387         assert(AUD_device);
388         assert(sound);
389
390         try
391         {
392                 if(AUD_3ddevice)
393                         return AUD_3ddevice->play3D(sound, keep);
394                 else
395                         return AUD_device->play(sound, keep);
396         }
397         catch(AUD_Exception)
398         {
399                 return NULL;
400         }
401 }
402
403 int AUD_updateListener(AUD_3DData* data)
404 {
405         assert(AUD_device);
406         assert(data);
407
408         try
409         {
410                 if(AUD_3ddevice)
411                         return AUD_3ddevice->updateListener(*data);
412         }
413         catch(AUD_Exception)
414         {
415         }
416         return false;
417 }
418
419 int AUD_set3DSetting(AUD_3DSetting setting, float value)
420 {
421         assert(AUD_device);
422
423         try
424         {
425                 if(AUD_3ddevice)
426                         return AUD_3ddevice->setSetting(setting, value);
427         }
428         catch(AUD_Exception)
429         {
430         }
431         return false;
432 }
433
434 float AUD_get3DSetting(AUD_3DSetting setting)
435 {
436         assert(AUD_device);
437
438         try
439         {
440                 if(AUD_3ddevice)
441                         return AUD_3ddevice->getSetting(setting);
442         }
443         catch(AUD_Exception)
444         {
445         }
446         return 0.0f;
447 }
448
449 int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data)
450 {
451         if(handle)
452         {
453                 assert(AUD_device);
454                 assert(data);
455
456                 try
457                 {
458                         if(AUD_3ddevice)
459                                 return AUD_3ddevice->updateSource(handle, *data);
460                 }
461                 catch(AUD_Exception)
462                 {
463                 }
464         }
465         return false;
466 }
467
468 int AUD_set3DSourceSetting(AUD_Handle* handle,
469                                                    AUD_3DSourceSetting setting, float value)
470 {
471         if(handle)
472         {
473                 assert(AUD_device);
474
475                 try
476                 {
477                         if(AUD_3ddevice)
478                                 return AUD_3ddevice->setSourceSetting(handle, setting, value);
479                 }
480                 catch(AUD_Exception)
481                 {
482                 }
483         }
484         return false;
485 }
486
487 float AUD_get3DSourceSetting(AUD_Handle* handle, AUD_3DSourceSetting setting)
488 {
489         if(handle)
490         {
491                 assert(AUD_device);
492
493                 try
494                 {
495                         if(AUD_3ddevice)
496                                 return AUD_3ddevice->getSourceSetting(handle, setting);
497                 }
498                 catch(AUD_Exception)
499                 {
500                 }
501         }
502         return 0.0f;
503 }
504
505 int AUD_setSoundVolume(AUD_Handle* handle, float volume)
506 {
507         if(handle)
508         {
509                 assert(AUD_device);
510                 AUD_SourceCaps caps;
511                 caps.handle = handle;
512                 caps.value = volume;
513
514                 try
515                 {
516                         return AUD_device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps);
517                 }
518                 catch(AUD_Exception) {}
519         }
520         return false;
521 }
522
523 int AUD_setSoundPitch(AUD_Handle* handle, float pitch)
524 {
525         if(handle)
526         {
527                 assert(AUD_device);
528                 AUD_SourceCaps caps;
529                 caps.handle = handle;
530                 caps.value = pitch;
531
532                 try
533                 {
534                         return AUD_device->setCapability(AUD_CAPS_SOURCE_PITCH, &caps);
535                 }
536                 catch(AUD_Exception) {}
537         }
538         return false;
539 }
540
541 AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
542 {
543         try
544         {
545                 return new AUD_ReadDevice(specs);
546         }
547         catch(AUD_Exception)
548         {
549                 return NULL;
550         }
551 }
552
553 AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
554 {
555         assert(device);
556         assert(sound);
557
558         try
559         {
560                 AUD_Handle* handle = device->play(sound);
561                 device->seek(handle, seek);
562                 return handle;
563         }
564         catch(AUD_Exception)
565         {
566                 return NULL;
567         }
568 }
569
570 int AUD_setDeviceVolume(AUD_Device* device, float volume)
571 {
572         assert(device);
573
574         try
575         {
576                 return device->setCapability(AUD_CAPS_VOLUME, &volume);
577         }
578         catch(AUD_Exception) {}
579         
580         return false;
581 }
582
583 int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle,
584                                                          float volume)
585 {
586         if(handle)
587         {
588                 assert(device);
589                 AUD_SourceCaps caps;
590                 caps.handle = handle;
591                 caps.value = volume;
592
593                 try
594                 {
595                         return device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps);
596                 }
597                 catch(AUD_Exception) {}
598         }
599         return false;
600 }
601
602 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
603 {
604         assert(device);
605         assert(buffer);
606
607         try
608         {
609                 return device->read(buffer, length);
610         }
611         catch(AUD_Exception)
612         {
613                 return false;
614         }
615 }
616
617 void AUD_closeReadDevice(AUD_Device* device)
618 {
619         assert(device);
620
621         try
622         {
623                 delete device;
624         }
625         catch(AUD_Exception)
626         {
627         }
628 }
629
630 float* AUD_readSoundBuffer(const char* filename, float low, float high,
631                                                    float attack, float release, float threshold,
632                                                    int accumulate, int additive, int square,
633                                                    float sthreshold, int samplerate, int* length)
634 {
635         AUD_Buffer buffer;
636         AUD_DeviceSpecs specs;
637         specs.channels = AUD_CHANNELS_MONO;
638         specs.rate = (AUD_SampleRate)samplerate;
639         AUD_Sound* sound;
640
641         AUD_FileFactory file(filename);
642         AUD_ChannelMapperFactory mapper(&file, specs);
643         AUD_LowpassFactory lowpass(&mapper, high);
644         AUD_HighpassFactory highpass(&lowpass, low);
645         AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f);
646         AUD_LinearResampleFactory resampler(&envelope, specs);
647         sound = &resampler;
648         AUD_SquareFactory squaref(sound, sthreshold);
649         if(square)
650                 sound = &squaref;
651         AUD_AccumulatorFactory accumulator(sound, additive);
652         AUD_SumFactory sum(sound);
653         if(accumulate)
654                 sound = &accumulator;
655         else if(additive)
656                 sound = &sum;
657
658         AUD_IReader* reader = sound->createReader();
659
660         if(reader == NULL)
661                 return NULL;
662
663         int len;
664         int position = 0;
665         sample_t* readbuffer;
666         do
667         {
668                 len = samplerate;
669                 buffer.resize((position + len) * sizeof(float), true);
670                 reader->read(len, readbuffer);
671                 memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float));
672                 position += len;
673         } while(len != 0);
674         delete reader;
675
676         float* result = (float*)malloc(position * sizeof(float));
677         memcpy(result, buffer.getBuffer(), position * sizeof(float));
678         *length = position;
679         return result;
680 }
681
682 AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
683 {
684 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
685  * is initialized.
686
687         return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
688 */
689         AUD_Specs specs;
690         specs.channels = AUD_CHANNELS_STEREO;
691         specs.rate = AUD_RATE_44100;
692         return new AUD_SequencerFactory(specs, data, volume);
693 }
694
695 void AUD_destroySequencer(AUD_Sound* sequencer)
696 {
697         delete ((AUD_SequencerFactory*)sequencer);
698 }
699
700 AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
701                                                                  float begin, float end, float skip, void* data)
702 {
703         return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
704 }
705
706 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
707 {
708         ((AUD_SequencerFactory*)sequencer)->remove(entry);
709 }
710
711 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
712                                    float begin, float end, float skip)
713 {
714         ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
715 }
716
717 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
718 {
719         ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
720 }
721
722 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
723 {
724         AUD_IReader* reader = sound->createReader();
725         AUD_DeviceSpecs specs;
726         sample_t* buf;
727
728         specs.specs = reader->getSpecs();
729         specs.channels = AUD_CHANNELS_MONO;
730         specs.format = AUD_FORMAT_FLOAT32;
731
732         AUD_ChannelMapperFactory mapper(reader, specs);
733
734         if(!reader || reader->getType() != AUD_TYPE_BUFFER)
735                 return -1;
736
737         reader = mapper.createReader();
738
739         if(!reader)
740                 return -1;
741
742         int len = reader->getLength();
743         float samplejump = (float)len / (float)length;
744         float min, max;
745
746         for(int i = 0; i < length; i++)
747         {
748                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
749                 reader->read(len, buf);
750
751                 if(len < 1)
752                 {
753                         length = i;
754                         break;
755                 }
756
757                 max = min = *buf;
758                 for(int j = 1; j < len; j++)
759                 {
760                         if(buf[j] < min)
761                                 min = buf[j];
762                         if(buf[j] > max)
763                                 max = buf[j];
764                         buffer[i * 2] = min;
765                         buffer[i * 2 + 1] = max;
766                 }
767         }
768
769         delete reader; AUD_DELETE("reader")
770
771         return length;
772 }
773
774 void AUD_startPlayback()
775 {
776 #ifdef WITH_JACK
777         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
778         if(device)
779                 device->startPlayback();
780 #endif
781 }
782
783 void AUD_stopPlayback()
784 {
785 #ifdef WITH_JACK
786         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
787         if(device)
788                 device->stopPlayback();
789 #endif
790 }
791
792 void AUD_seekSequencer(AUD_Handle* handle, float time)
793 {
794 #ifdef WITH_JACK
795         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
796         if(device)
797                 device->seekPlayback(time);
798         else
799 #endif
800         {
801                 AUD_device->seek(handle, time);
802         }
803 }
804
805 float AUD_getSequencerPosition(AUD_Handle* handle)
806 {
807 #ifdef WITH_JACK
808         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
809         if(device)
810                 return device->getPlaybackPosition();
811         else
812 #endif
813         {
814                 return AUD_device->getPosition(handle);
815         }
816 }
817
818 #ifdef WITH_JACK
819 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
820 {
821         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
822         if(device)
823                 device->setSyncCallback(function, data);
824 }
825 #endif
826
827 int AUD_doesPlayback()
828 {
829 #ifdef WITH_JACK
830         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
831         if(device)
832                 return device->doesPlayback();
833 #endif
834         return -1;
835 }
836
837 #ifdef AUD_DEBUG_MEMORY
838 int AUD_References(int count, const char* text)
839 {
840         static int m_count = 0;
841         m_count += count;
842         if(count > 0)
843                 printf("+%s\n", text);
844         if(count < 0)
845                 printf("-%s\n", text);
846         return m_count;
847 }
848 #endif