00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <glib.h>
00019 #include <math.h>
00020 #include "xmmspriv/xmms_sample.h"
00021 #include "xmms/xmms_medialib.h"
00022 #include "xmms/xmms_object.h"
00023 #include "xmms/xmms_log.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 struct xmms_sample_converter_St {
00036 xmms_object_t obj;
00037
00038 xmms_stream_type_t *from;
00039 xmms_stream_type_t *to;
00040
00041 gboolean same;
00042 gboolean resample;
00043
00044
00045 guint bufsiz;
00046 xmms_sample_t *buf;
00047
00048 guint interpolator_ratio;
00049 guint decimator_ratio;
00050
00051 guint offset;
00052
00053 xmms_sample_t *state;
00054
00055 xmms_sample_conv_func_t func;
00056
00057 };
00058
00059 static void recalculate_resampler (xmms_sample_converter_t *conv, guint from, guint to);
00060 static xmms_sample_conv_func_t
00061 xmms_sample_conv_get (guint inchannels, xmms_sample_format_t intype,
00062 guint outchannels, xmms_sample_format_t outtype,
00063 gboolean resample);
00064
00065
00066
00067 static void
00068 xmms_sample_converter_destroy (xmms_object_t *obj)
00069 {
00070 xmms_sample_converter_t *conv = (xmms_sample_converter_t *) obj;
00071
00072 g_free (conv->buf);
00073 g_free (conv->state);
00074 }
00075
00076 xmms_sample_converter_t *
00077 xmms_sample_converter_init (xmms_stream_type_t *from, xmms_stream_type_t *to)
00078 {
00079 xmms_sample_converter_t *conv = xmms_object_new (xmms_sample_converter_t, xmms_sample_converter_destroy);
00080 gint fformat, fsamplerate, fchannels;
00081 gint tformat, tsamplerate, tchannels;
00082
00083 fformat = xmms_stream_type_get_int (from, XMMS_STREAM_TYPE_FMT_FORMAT);
00084 fsamplerate = xmms_stream_type_get_int (from, XMMS_STREAM_TYPE_FMT_SAMPLERATE);
00085 fchannels = xmms_stream_type_get_int (from, XMMS_STREAM_TYPE_FMT_CHANNELS);
00086 tformat = xmms_stream_type_get_int (to, XMMS_STREAM_TYPE_FMT_FORMAT);
00087 tsamplerate = xmms_stream_type_get_int (to, XMMS_STREAM_TYPE_FMT_SAMPLERATE);
00088 tchannels = xmms_stream_type_get_int (to, XMMS_STREAM_TYPE_FMT_CHANNELS);
00089
00090 g_return_val_if_fail (tformat != -1, NULL);
00091 g_return_val_if_fail (tchannels != -1, NULL);
00092 g_return_val_if_fail (tsamplerate != -1, NULL);
00093
00094 conv->from = from;
00095 conv->to = to;
00096
00097 conv->resample = fsamplerate != tsamplerate;
00098
00099 conv->func = xmms_sample_conv_get (fchannels, fformat,
00100 tchannels, tformat,
00101 conv->resample);
00102
00103 if (!conv->func) {
00104 xmms_object_unref (conv);
00105 xmms_log_error ("Unable to convert from %s/%d/%d to %s/%d/%d.",
00106 xmms_sample_name_get (fformat), fsamplerate, fchannels,
00107 xmms_sample_name_get (tformat), tsamplerate, tchannels);
00108 return NULL;
00109 }
00110
00111 if (conv->resample)
00112 recalculate_resampler (conv, fsamplerate, tsamplerate);
00113
00114 return conv;
00115 }
00116
00117
00118
00119
00120 xmms_stream_type_t *
00121 xmms_sample_converter_get_from (xmms_sample_converter_t *conv)
00122 {
00123 g_return_val_if_fail (conv, NULL);
00124
00125 return conv->from;
00126 }
00127
00128
00129
00130
00131 xmms_stream_type_t *
00132 xmms_sample_converter_get_to (xmms_sample_converter_t *conv)
00133 {
00134 g_return_val_if_fail (conv, NULL);
00135
00136 return conv->to;
00137 }
00138
00139
00140
00141 void
00142 xmms_sample_converter_to_medialib (xmms_sample_converter_t *conv, xmms_medialib_entry_t entry)
00143 {
00144 #if 0
00145 xmms_medialib_session_t *session;
00146
00147 session = xmms_medialib_begin_write ();
00148 xmms_medialib_entry_property_set_str (session, entry,
00149 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLEFMT_IN,
00150 xmms_sample_name_get (conv->from->format));
00151 xmms_medialib_entry_property_set_int (session, entry,
00152 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLERATE_IN,
00153 conv->from->samplerate);
00154 xmms_medialib_entry_property_set_int (session, entry,
00155 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_CHANNELS_IN,
00156 conv->from->channels);
00157
00158 xmms_medialib_entry_property_set_str (session, entry,
00159 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLEFMT_OUT,
00160 xmms_sample_name_get (conv->to->format));
00161 xmms_medialib_entry_property_set_int (session, entry,
00162 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLERATE_OUT,
00163 conv->to->samplerate);
00164 xmms_medialib_entry_property_set_int (session, entry,
00165 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_CHANNELS_OUT,
00166 conv->to->channels);
00167
00168 xmms_medialib_end (session);
00169 #endif
00170 }
00171
00172
00173
00174
00175
00176 guint
00177 xmms_sample_ms_to_samples (const xmms_stream_type_t *st, guint milliseconds)
00178 {
00179 gint rate;
00180 rate = xmms_stream_type_get_int (st, XMMS_STREAM_TYPE_FMT_SAMPLERATE);
00181 return (guint)(((gdouble) rate) * milliseconds / 1000);
00182 }
00183
00184
00185
00186
00187 guint
00188 xmms_sample_samples_to_ms (const xmms_stream_type_t *st, guint samples)
00189 {
00190 gint rate;
00191 rate = xmms_stream_type_get_int (st, XMMS_STREAM_TYPE_FMT_SAMPLERATE);
00192 return (guint) (((gdouble)samples) * 1000.0 / rate);
00193 }
00194
00195
00196
00197
00198 guint
00199 xmms_sample_bytes_to_ms (const xmms_stream_type_t *st, guint bytes)
00200 {
00201 guint samples = bytes / xmms_sample_frame_size_get (st);
00202 return xmms_sample_samples_to_ms (st, samples);
00203 }
00204
00205 gint
00206 xmms_sample_frame_size_get (const xmms_stream_type_t *st)
00207 {
00208 gint format, channels;
00209 format = xmms_stream_type_get_int (st, XMMS_STREAM_TYPE_FMT_FORMAT);
00210 channels = xmms_stream_type_get_int (st, XMMS_STREAM_TYPE_FMT_CHANNELS);
00211 return xmms_sample_size_get (format) * channels;
00212 }
00213
00214 static void
00215 recalculate_resampler (xmms_sample_converter_t *conv, guint from, guint to)
00216 {
00217 guint a,b;
00218
00219
00220 if (from > to){
00221 a = from;
00222 b = to;
00223 } else {
00224 b = to;
00225 a = from;
00226 }
00227
00228 while (b != 0) {
00229 guint t = a % b;
00230 a = b;
00231 b = t;
00232 }
00233
00234 XMMS_DBG ("Resampling ratio: %d:%d",
00235 from / a, to / a);
00236
00237 conv->interpolator_ratio = to/a;
00238 conv->decimator_ratio = from/a;
00239
00240 conv->state = g_malloc0 (xmms_sample_frame_size_get (conv->from));
00241
00242
00243
00244
00245
00246
00247
00248
00249 }
00250
00251
00252
00253
00254
00255 void
00256 xmms_sample_convert (xmms_sample_converter_t *conv, xmms_sample_t *in, guint len, xmms_sample_t **out, guint *outlen)
00257 {
00258 int inusiz, outusiz;
00259 int olen;
00260 guint res;
00261
00262 inusiz = xmms_sample_frame_size_get (conv->from);
00263
00264 g_return_if_fail (len % inusiz == 0);
00265
00266 if (conv->same) {
00267 *outlen = len;
00268 *out = in;
00269 return;
00270 }
00271
00272 len /= inusiz;
00273
00274 outusiz = xmms_sample_frame_size_get (conv->to);
00275
00276 if (conv->resample) {
00277 olen = (len * conv->interpolator_ratio / conv->decimator_ratio) * outusiz + outusiz;
00278 } else {
00279 olen = len * outusiz;
00280 }
00281 if (olen > conv->bufsiz) {
00282 void *t;
00283 t = g_realloc (conv->buf, olen);
00284 g_assert (t);
00285 conv->buf = t;
00286 conv->bufsiz = olen;
00287 }
00288
00289 res = conv->func (conv, in, len, conv->buf);
00290
00291 *outlen = res * outusiz;
00292 *out = conv->buf;
00293
00294 }
00295
00296 gint64
00297 xmms_sample_convert_scale (xmms_sample_converter_t *conv, gint64 samples)
00298 {
00299
00300
00301
00302
00303 if (!conv->resample)
00304 return samples;
00305 return samples * conv->decimator_ratio / conv->interpolator_ratio;
00306 }
00307
00308 gint64
00309 xmms_sample_convert_rev_scale (xmms_sample_converter_t *conv, gint64 samples)
00310 {
00311 if (!conv->resample)
00312 return samples;
00313 return samples * conv->interpolator_ratio / conv->decimator_ratio;
00314 }
00315
00316 void
00317 xmms_sample_convert_reset (xmms_sample_converter_t *conv)
00318 {
00319 if (conv->resample) {
00320 conv->offset = 0;
00321 memset (conv->state, 0, xmms_sample_frame_size_get (conv->from));
00322 }
00323 }
00324
00325
00326
00327