1 /*******************************************************************************
2 *                         Goggles Audio Player Library                         *
3 ********************************************************************************
4 *           Copyright (C) 2010-2021 by Sander Jansen. All Rights Reserved      *
5 *                               ---                                            *
6 * This program is free software: you can redistribute it and/or modify         *
7 * it under the terms of the GNU General Public License as published by         *
8 * the Free Software Foundation, either version 3 of the License, or            *
9 * (at your option) any later version.                                          *
10 *                                                                              *
11 * This program is distributed in the hope that it will be useful,              *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of               *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                *
14 * GNU General Public License for more details.                                 *
15 *                                                                              *
16 * You should have received a copy of the GNU General Public License            *
17 * along with this program.  If not, see http://www.gnu.org/licenses.           *
18 ********************************************************************************/
19 #include "ap_defs.h"
20 #include "ap_format.h"
21 #include "ap_common.h"
22 
23 
24 namespace ap {
25 
26 static const FXchar * const channelnames[]={
27   "NA","MONO","FL","FR","FC","BL","BR","BC","SL","SR","LFE"
28   };
29 
30 static const FXchar * const codecs[]={
31   "Invalid",
32   "PCM",
33   "FLAC",
34   "Vorbis",
35   "MPEG",
36   "AAC",
37   "Opus",
38   "ALAC",
39   "DCA",
40   "A52"
41   };
42 
43 static const FXchar * const byteorders[]={
44   "le",
45   "be"
46   };
47 
48 static const FXchar * const formats[]={
49   "s",
50   "u",
51   "f",
52   "iec958_frame"
53   "Reserved1"
54   "Reserved2"
55   "Reserved3"
56   "Reserved4"
57   };
58 
59 
60 static const FXchar * const formatnames[]={
61   "unknown",
62   "wav",
63   "ogg",
64   "flac",
65   "mp3",
66   "mp4",
67   "aac",
68   "m3u",
69   "pls",
70   "xspf",
71   "aiff",
72   "matroska"
73   };
74 
75 
name(FXuchar c)76 const FXchar * Codec::name(FXuchar c){
77   return codecs[c];
78   }
79 
80 
81 
82 
83 #if defined(HAVE_OPUS) || defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
84 
85 // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
86 extern const FXuint vorbis_channel_map[]={
87   AP_CHANNELMAP_MONO,
88 
89   AP_CHANNELMAP_STEREO,
90 
91   AP_CMAP3(Channel::FrontLeft,
92            Channel::FrontCenter,
93            Channel::FrontRight),
94 
95   AP_CMAP4(Channel::FrontLeft,
96            Channel::FrontRight,
97            Channel::BackLeft,
98            Channel::BackRight),
99 
100   AP_CMAP5(Channel::FrontLeft,
101            Channel::FrontCenter,
102            Channel::FrontRight,
103            Channel::BackLeft,
104            Channel::BackRight),
105 
106   AP_CMAP6(Channel::FrontLeft,
107            Channel::FrontCenter,
108            Channel::FrontRight,
109            Channel::BackLeft,
110            Channel::BackRight,
111            Channel::LFE),
112 
113   AP_CMAP7(Channel::FrontLeft,
114            Channel::FrontCenter,
115            Channel::FrontRight,
116            Channel::SideLeft,
117            Channel::SideRight,
118            Channel::BackCenter,
119            Channel::LFE),
120 
121   AP_CMAP8(Channel::FrontLeft,
122            Channel::FrontCenter,
123            Channel::FrontRight,
124            Channel::SideLeft,
125            Channel::SideRight,
126            Channel::BackLeft,
127            Channel::BackRight,
128            Channel::LFE)
129   };
130 
131 #endif
132 
133 
reset()134 void AudioFormat::reset() {
135   format=0;
136   rate=0;
137   channels=0;
138   channelmap=0;
139   }
140 
setBits(FXushort bits)141 void AudioFormat::setBits(FXushort bits) {
142   if (bits>0 && bits<=32) {
143     format|=(bits-1)<<Format::Bits_Shift|(((bits/8)-1)<<Format::Pack_Shift);
144     }
145   }
146 
setChannels(FXuchar ch)147 void AudioFormat::setChannels(FXuchar ch) {
148   if (ch>0 && ch<=8) {
149     channels=ch;
150     switch(channels) {
151       case  1: channelmap = AP_CHANNELMAP_MONO;   break;
152       case  2: channelmap = AP_CHANNELMAP_STEREO; break;
153       default: channelmap = 0;                    break;
154       }
155     }
156   }
157 
158 
set(FXushort dt,FXushort bits,FXushort pack,FXuint r,FXuchar nc,FXuint map)159 void AudioFormat::set(FXushort dt,FXushort bits,FXushort pack,FXuint r,FXuchar nc,FXuint map) {
160   format=dt|((bits-1)<<Format::Bits_Shift)|((pack-1)<<Format::Pack_Shift);
161   rate=r;
162   channels=nc;
163   channelmap=map;
164   if (channelmap==0) {
165     switch(channels) {
166       case  1: channelmap = AP_CHANNELMAP_MONO;   break;
167       case  2: channelmap = AP_CHANNELMAP_STEREO; break;
168       default: channelmap = 0;                    break;
169       };
170     }
171   }
172 
set(FXushort fmt,FXuint r,FXuchar nc,FXuint map)173 void AudioFormat::set(FXushort fmt,FXuint r,FXuchar nc,FXuint map) {
174   format=fmt;
175   rate=r;
176   channels=nc;
177   channelmap=map;
178   if (channelmap==0) {
179     switch(channels) {
180       case  1: channelmap = AP_CHANNELMAP_MONO;   break;
181       case  2: channelmap = AP_CHANNELMAP_STEREO; break;
182       default: channelmap = 0;                    break;
183       };
184     }
185   }
186 
187 
swap()188 FXbool AudioFormat::swap() {
189   if (packing()>Format::Pack_1) {
190     format^=(1<<Format::Order_Shift);
191     return true;
192     }
193   else {
194     return false;
195     }
196   }
197 
198 
199 /*
200   24 -> 32 -> 16
201   flt -> 32 -> 16
202 */
203 
compatible()204 FXbool AudioFormat::compatible()  {
205   switch(format){
206     case AP_FORMAT_S24_3BE  : format=AP_FORMAT_S24_BE; break;
207     case AP_FORMAT_S24_3LE  : format=AP_FORMAT_S24_LE; break;
208     case AP_FORMAT_S24_LE   : format=AP_FORMAT_S32_LE; break;
209     case AP_FORMAT_S24_BE   : format=AP_FORMAT_S32_BE; break;
210     case AP_FORMAT_S32_LE   : format=AP_FORMAT_S16_LE; break;
211     case AP_FORMAT_S32_BE   : format=AP_FORMAT_S16_BE; break;
212     case AP_FORMAT_FLOAT_LE : format=AP_FORMAT_S32_LE; break;
213     case AP_FORMAT_FLOAT_BE : format=AP_FORMAT_S32_BE; break;
214     default                 : return false;            break;
215     }
216   return true;
217   }
218 
219 
debug_format() const220 FXString AudioFormat::debug_format() const {
221   return FXString::value("%s%2d%s%d",formats[datatype()],bps(),byteorders[byteorder()],packing());
222   }
223 
debug() const224 void AudioFormat::debug() const {
225   fxmessage("format: %6dHz, %dch, %s%2d%s%d",rate,channels,formats[datatype()],bps(),byteorders[byteorder()],packing());
226   if (channels) {
227     fxmessage(", (%s",channelnames[channeltype(0)]);
228     for (FXuint i=1;i<channels;i++) {
229       fxmessage(",%s",channelnames[channeltype(i)]);
230       }
231     fxmessage(")\n");
232     }
233   else {
234     fxmessage("\n");
235     }
236   }
237 
238 
operator !=(const AudioFormat & af1,const AudioFormat & af2)239 FXbool operator!=(const AudioFormat& af1,const AudioFormat& af2){
240   if ( (af1.format!=af2.format) ||
241        (af1.rate!=af2.rate) ||
242        (af1.channels!=af2.channels) ||
243        (af1.channelmap!=af2.channelmap) )
244     return true;
245   else
246     return false;
247   }
248 
operator ==(const AudioFormat & af1,const AudioFormat & af2)249 FXbool operator==(const AudioFormat& af1,const AudioFormat& af2){
250   if ( (af1.format!=af2.format) ||
251        (af1.rate!=af2.rate) ||
252        (af1.channels!=af2.channels) ||
253        (af1.channelmap!=af2.channelmap) )
254     return false;
255   else
256     return true;
257   }
258 
259 
ap_format_from_mime(const FXString & mime)260 extern FXuint ap_format_from_mime(const FXString & mime) {
261   if (comparecase(mime,"audio/mpeg")==0) {
262     return Format::MP3;
263     }
264   else if (comparecase(mime,"audio/ogg")==0 ||
265            comparecase(mime,"application/ogg")==0 ||
266            comparecase(mime,"audio/opus")==0){
267     return Format::OGG;
268     }
269   else if (comparecase(mime,"audio/aacp")==0 ||
270            comparecase(mime,"audio/aac")==0) {
271     return Format::AAC;
272     }
273   else if (comparecase(mime,"audio/x-mpegurl")==0 ||
274            comparecase(mime,"audio/mpegurl")==0) {
275     return Format::M3U;
276     }
277   else if ((comparecase(mime,"application/pls+xml")==0) || /// wrong mimetype, but NPR actually returns this: http://www.npr.org/streams/mp3/nprlive24.pls
278            (comparecase(mime,"audio/x-scpls")==0)){
279     return Format::PLS;
280     }
281   else if (comparecase(mime,"application/xspf+xml")==0){
282     return Format::XSPF;
283     }
284   else if (comparecase(mime,"audio/x-aiff")==0 ||
285            comparecase(mime,"audio/aiff")==0) {
286     return Format::AIFF;
287     }
288   else if (comparecase(mime,"video/webm")==0){
289     return Format::Matroska;
290     }
291 
292   else {
293     return Format::Unknown;
294     }
295   }
296 
ap_format_from_extension(const FXString & extension)297 extern FXuint ap_format_from_extension(const FXString & extension) {
298   if (comparecase(extension,"wav")==0)
299     return Format::WAV;
300   else if (comparecase(extension,"flac")==0)
301     return Format::FLAC;
302   else if (comparecase(extension,"ogg")==0 || comparecase(extension,"oga")==0 || comparecase(extension,"opus")==0)
303     return Format::OGG;
304   else if (comparecase(extension,"mp3")==0)
305     return Format::MP3;
306   else if (comparecase(extension,"mp4")==0 ||
307            comparecase(extension,"m4a")==0 ||
308            comparecase(extension,"m4p")==0 ||
309            comparecase(extension,"mov")==0 ||
310            comparecase(extension,"m4b")==0 )
311     return Format::MP4;
312   else if (comparecase(extension,"aac")==0)
313     return Format::AAC;
314   else if (comparecase(extension,"aiff")==0 || comparecase(extension,"aif")==0)
315     return Format::AIFF;
316   else if (comparecase(extension,"m3u")==0)
317     return Format::M3U;
318   else if (comparecase(extension,"pls")==0)
319     return Format::PLS;
320   else if (comparecase(extension,"xspf")==0)
321     return Format::XSPF;
322   else if (comparecase(extension,"mkv")==0 || comparecase(extension,"webm")==0)
323     return Format::Matroska;
324   else
325     return Format::Unknown;
326   }
327 
328 
ap_format_from_buffer(const FXchar *,FXival)329 extern FXuint ap_format_from_buffer(const FXchar * /*buffer*/,FXival /*size*/) {
330   return Format::Unknown;
331   }
332 
ap_format_name(FXuint format)333 extern const FXchar * ap_format_name(FXuint format){
334   return formatnames[format];
335   }
336 
337 
ap_get_gogglesmm_all_supported_files()338 extern FXString ap_get_gogglesmm_all_supported_files() {
339   const FXchar * const supported = "*.("
340 #if defined(HAVE_OPUS)
341   "opus,"
342 #endif
343 #if defined(HAVE_FLAC)
344   "flac,oga,"
345 #endif
346 #if defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
347   "ogg,"
348 #endif
349 #if defined(HAVE_MAD)
350   "mp3,"
351 #endif
352 #if defined(HAVE_MP4)
353   "mp4,m4a,m4b,m4p,mov,"
354 #endif
355 #if defined(HAVE_FAAD)
356   "aac,"
357 #endif
358 #if defined(HAVE_MATROSKA)
359   "mkv,mka,webm,"
360 #endif
361   "wav,aiff)"
362   ;
363   return supported;
364   }
365 
366 
ap_get_gogglesmm_supported_files()367 extern FXString ap_get_gogglesmm_supported_files() {
368   FXString pattern;
369   const FXchar * const supported = "*.("
370 #if defined(HAVE_OPUS)
371   "opus,"
372 #endif
373 #if defined(HAVE_FLAC)
374   "flac,oga,"
375 #endif
376 #if defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
377   "ogg,"
378 #endif
379 #if defined(HAVE_MAD)
380   "mp3,"
381 #endif
382 #if defined(HAVE_MP4)
383   "mp4,m4a,m4b,m4p,mov,"
384 #endif
385 #if defined(HAVE_FAAD)
386   "aac,"
387 #endif
388   ;
389 
390   if (strlen(supported)==3)
391     return FXString::null;
392 
393   pattern = supported;
394   pattern.tail() = ')';
395   return pattern;
396   }
397 
398 
ap_get_gogglesmm_filepatterns()399 extern FXString ap_get_gogglesmm_filepatterns() {
400   const FXchar * const patterns =
401 
402  "All Music ("
403 #if defined(HAVE_OPUS)
404   "*.opus,"
405 #endif
406 #if defined(HAVE_FLAC)
407   "*.flac,*.oga,"
408 #endif
409 #if defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
410   "*.ogg,"
411 #endif
412 #if defined(HAVE_MAD)
413   "*.mp3,"
414 #endif
415 #if defined(HAVE_MP4)
416   "*.mp4,*.m4a,*.m4b,*.m4p,*.mov,"
417 #endif
418 #if defined(HAVE_FAAD)
419   "*.aac,"
420 #endif
421 #if defined(HAVE_MATROSKA)
422   "*.mka,*.webm"
423 #endif
424   "*.wav,*.aiff)\n"
425 
426 // All Media
427 
428   "All Media ("
429 #if defined(HAVE_OPUS)
430   "*.opus,"
431 #endif
432 #if defined(HAVE_FLAC)
433   "*.flac,*.oga,"
434 #endif
435 #if defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
436   "*.ogg,"
437 #endif
438 #if defined(HAVE_MAD)
439   "*.mp3,"
440 #endif
441 #if defined(HAVE_MP4)
442   "*.mp4,*.m4a,*.m4b,*.m4p,*.mov,"
443 #endif
444 #if defined(HAVE_FAAD)
445   "*.aac,"
446 #endif
447 #if defined(HAVE_MATROSKA)
448   "*.mkv,*.mka,*.webm"
449 #endif
450   "*.wav,*.aiff)\n"
451 
452 #if defined(HAVE_OPUS)
453   "Opus (*.opus)\n"
454 #endif
455 #if defined(HAVE_FLAC)
456   "Free Lossless Audio Codec (*.flac,*.oga)\n"
457 #endif
458 #if defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
459   "Ogg Vorbis (*.ogg)\n"
460 #endif
461 #if defined(HAVE_MAD)
462   "MPEG-1 Audio Layer 3 (*.mp3)\n"
463 #endif
464 #if defined(HAVE_MP4)
465   "MPEG-4 Part 14 (*.mp4,*.m4a,*.m4p,*.m4b,*.mov)\n"
466 #endif
467 #if defined(HAVE_FAAD)
468   "Advanced Audio Coding (*.aac)\n"
469 #endif
470 #if defined(HAVE_MATROSKA)
471   "Matroska (*.mka,*.webm)"
472 #endif
473   "Wav (*.wav,*.aiff)\n";
474 
475   return patterns;
476   }
477 
478 
479 
480 
481 
482 
483 
484 }
485