2 Copyright (C) 2011-2013 Robin Gareus <robin@gareus.org>
3 Copyright (C) 2014-2023 Filipe Coelho <falktx@falktx.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser Public License as published by
7 the Free Software Foundation; either version 2.1, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "ad_plugin.h"
33 #define strcasecmp stricmp
36 /* internal abstraction */
41 } sndfile_audio_decoder
;
43 static int parse_bit_depth(int format
) {
44 /* see http://www.mega-nerd.com/libsndfile/api.html */
45 switch (format
&0x0f) {
46 case SF_FORMAT_PCM_S8
: return 8;
47 case SF_FORMAT_PCM_16
: return 16; /* Signed 16 bit data */
48 case SF_FORMAT_PCM_24
: return 24; /* Signed 24 bit data */
49 case SF_FORMAT_PCM_32
: return 32; /* Signed 32 bit data */
50 case SF_FORMAT_PCM_U8
: return 8; /* Unsigned 8 bit data (WAV and RAW only) */
51 case SF_FORMAT_FLOAT
: return 32; /* 32 bit float data */
52 case SF_FORMAT_DOUBLE
: return 64; /* 64 bit float data */
58 static int ad_info_sndfile(void *sf
, struct adinfo
*nfo
) {
59 sndfile_audio_decoder
*priv
= (sndfile_audio_decoder
*) sf
;
62 nfo
->channels
= priv
->sfinfo
.channels
;
63 nfo
->frames
= priv
->sfinfo
.frames
;
64 nfo
->sample_rate
= priv
->sfinfo
.samplerate
;
65 nfo
->length
= priv
->sfinfo
.samplerate
? (priv
->sfinfo
.frames
* 1000) / priv
->sfinfo
.samplerate
: 0;
66 nfo
->bit_depth
= parse_bit_depth(priv
->sfinfo
.format
);
67 nfo
->bit_rate
= nfo
->bit_depth
* nfo
->channels
* nfo
->sample_rate
;
68 nfo
->meta_data
= NULL
;
74 static void *ad_open_sndfile(const char *fn
, struct adinfo
*nfo
) {
75 sndfile_audio_decoder
*priv
= (sndfile_audio_decoder
*) calloc(1, sizeof(sndfile_audio_decoder
));
76 priv
->sfinfo
.format
=0;
77 if(!(priv
->sffile
= sf_open(fn
, SFM_READ
, &priv
->sfinfo
))){
78 dbg(0, "unable to open file '%s'.", fn
);
79 puts(sf_strerror(NULL
));
80 int e
= sf_error(NULL
);
81 dbg(0, "error=%i", e
);
85 ad_info_sndfile(priv
, nfo
);
89 static int ad_close_sndfile(void *sf
) {
90 sndfile_audio_decoder
*priv
= (sndfile_audio_decoder
*) sf
;
92 if(!sf
|| sf_close(priv
->sffile
)) {
93 dbg(0, "fatal: bad file close.\n");
100 static int64_t ad_seek_sndfile(void *sf
, int64_t pos
) {
101 sndfile_audio_decoder
*priv
= (sndfile_audio_decoder
*) sf
;
102 if (!priv
) return -1;
103 return sf_seek(priv
->sffile
, pos
, SEEK_SET
);
106 static ssize_t
ad_read_sndfile(void *sf
, float* d
, size_t len
) {
107 sndfile_audio_decoder
*priv
= (sndfile_audio_decoder
*) sf
;
108 if (!priv
) return -1;
109 return sf_read_float (priv
->sffile
, d
, len
);
112 static int ad_get_bitrate_sndfile(void *sf
) {
113 sndfile_audio_decoder
*priv
= (sndfile_audio_decoder
*) sf
;
114 if (!priv
) return -1;
115 return parse_bit_depth(priv
->sfinfo
.format
) * priv
->sfinfo
.channels
* priv
->sfinfo
.samplerate
;
118 static int ad_eval_sndfile(const char *f
) {
119 char *ext
= strrchr(f
, '.');
120 if (strstr (f
, "://")) return 0;
122 /* see http://www.mega-nerd.com/libsndfile/ */
123 if (!strcasecmp(ext
, ".wav")) return 100;
124 if (!strcasecmp(ext
, ".aiff")) return 100;
125 if (!strcasecmp(ext
, ".aifc")) return 100;
126 if (!strcasecmp(ext
, ".snd")) return 100;
127 if (!strcasecmp(ext
, ".au")) return 100;
128 if (!strcasecmp(ext
, ".paf")) return 100;
129 if (!strcasecmp(ext
, ".iff")) return 100;
130 if (!strcasecmp(ext
, ".svx")) return 100;
131 if (!strcasecmp(ext
, ".sf")) return 100;
132 if (!strcasecmp(ext
, ".vcc")) return 100;
133 if (!strcasecmp(ext
, ".w64")) return 100;
134 if (!strcasecmp(ext
, ".mat4")) return 100;
135 if (!strcasecmp(ext
, ".mat5")) return 100;
136 if (!strcasecmp(ext
, ".pvf5")) return 100;
137 if (!strcasecmp(ext
, ".xi")) return 100;
138 if (!strcasecmp(ext
, ".htk")) return 100;
139 if (!strcasecmp(ext
, ".pvf")) return 100;
140 if (!strcasecmp(ext
, ".sd2")) return 100;
141 // libsndfile >= 1.0.18
142 if (!strcasecmp(ext
, ".flac")) return 80;
143 if (!strcasecmp(ext
, ".oga")) return 80;
144 if (!strcasecmp(ext
, ".ogg")) return 80;
145 if (!strcasecmp(ext
, ".opus")) return 80;
150 static const ad_plugin ad_sndfile
= {
158 &ad_get_bitrate_sndfile
171 const ad_plugin
* adp_get_sndfile() {