Add initial bits for Qt6 support
[carla.git] / source / modules / audio_decoder / ad_soundfile.c
blobc540e1c03c75ccc64496c60eac04a2ea0de18403
1 /**
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)
8 any later version.
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
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
26 #include "ad_plugin.h"
28 #ifdef HAVE_SNDFILE
30 #include <sndfile.h>
32 #ifdef _MSC_VER
33 #define strcasecmp stricmp
34 #endif
36 /* internal abstraction */
38 typedef struct {
39 SF_INFO sfinfo;
40 SNDFILE *sffile;
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 */
53 default: break;
55 return 16;
58 static int ad_info_sndfile(void *sf, struct adinfo *nfo) {
59 sndfile_audio_decoder *priv = (sndfile_audio_decoder*) sf;
60 if (!priv) return -1;
61 if (nfo) {
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;
69 nfo->can_seek = 1;
71 return 0;
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);
82 free(priv);
83 return NULL;
85 ad_info_sndfile(priv, nfo);
86 return (void*) priv;
89 static int ad_close_sndfile(void *sf) {
90 sndfile_audio_decoder *priv = (sndfile_audio_decoder*) sf;
91 if (!priv) return -1;
92 if(!sf || sf_close(priv->sffile)) {
93 dbg(0, "fatal: bad file close.\n");
94 return -1;
96 free(priv);
97 return 0;
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;
121 if (!ext) return 5;
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;
146 return 0;
148 #endif
150 static const ad_plugin ad_sndfile = {
151 #ifdef HAVE_SNDFILE
152 &ad_eval_sndfile,
153 &ad_open_sndfile,
154 &ad_close_sndfile,
155 &ad_info_sndfile,
156 &ad_seek_sndfile,
157 &ad_read_sndfile,
158 &ad_get_bitrate_sndfile
159 #else
160 &ad_eval_null,
161 &ad_open_null,
162 &ad_close_null,
163 &ad_info_null,
164 &ad_seek_null,
165 &ad_read_null,
166 &ad_bitrate_null
167 #endif
170 /* dlopen handler */
171 const ad_plugin * adp_get_sndfile() {
172 return &ad_sndfile;