XMMS2
sample.head.c
Go to the documentation of this file.
1/* XMMS2 - X Music Multiplexer System
2 * Copyright (C) 2003-2011 XMMS2 Team
3 *
4 * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 */
16
17
18#include <glib.h>
19#include <math.h>
21#include "xmms/xmms_medialib.h"
22#include "xmms/xmms_object.h"
23#include "xmms/xmms_log.h"
24
25/**
26 * @defgroup Sample Sample Converter
27 * @ingroup XMMSServer
28 * @brief Convert sample formats back and forth.
29 * @{
30 */
31
32/**
33 * The converter module
34 */
35struct xmms_sample_converter_St {
36 xmms_object_t obj;
37
40
41 gboolean same;
42 gboolean resample;
43
44 /* buffer for result */
45 guint bufsiz;
46 xmms_sample_t *buf;
47
48 guint interpolator_ratio;
49 guint decimator_ratio;
50
51 guint offset;
52
53 xmms_sample_t *state;
54
56
57};
58
59static void recalculate_resampler (xmms_sample_converter_t *conv, guint from, guint to);
61xmms_sample_conv_get (guint inchannels, xmms_sample_format_t intype,
62 guint outchannels, xmms_sample_format_t outtype,
63 gboolean resample);
64
65
66
67static void
68xmms_sample_converter_destroy (xmms_object_t *obj)
69{
71
72 g_free (conv->buf);
73 g_free (conv->state);
74}
75
78{
79 xmms_sample_converter_t *conv = xmms_object_new (xmms_sample_converter_t, xmms_sample_converter_destroy);
80 gint fformat, fsamplerate, fchannels;
81 gint tformat, tsamplerate, tchannels;
82
89
90 g_return_val_if_fail (tformat != -1, NULL);
91 g_return_val_if_fail (tchannels != -1, NULL);
92 g_return_val_if_fail (tsamplerate != -1, NULL);
93
94 conv->from = from;
95 conv->to = to;
96
97 conv->resample = fsamplerate != tsamplerate;
98
99 conv->func = xmms_sample_conv_get (fchannels, fformat,
100 tchannels, tformat,
101 conv->resample);
102
103 if (!conv->func) {
104 xmms_object_unref (conv);
105 xmms_log_error ("Unable to convert from %s/%d/%d to %s/%d/%d.",
106 xmms_sample_name_get (fformat), fsamplerate, fchannels,
107 xmms_sample_name_get (tformat), tsamplerate, tchannels);
108 return NULL;
109 }
110
111 if (conv->resample)
112 recalculate_resampler (conv, fsamplerate, tsamplerate);
113
114 return conv;
115}
116
117/**
118 * Return the audio format used by the converter as source
119 */
122{
123 g_return_val_if_fail (conv, NULL);
124
125 return conv->from;
126}
127
128/**
129 * Return the audio format used by the converter as target
130 */
133{
134 g_return_val_if_fail (conv, NULL);
135
136 return conv->to;
137}
138
139/**
140 */
141void
143{
144#if 0
146
147 session = xmms_medialib_begin_write ();
149 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLEFMT_IN,
150 xmms_sample_name_get (conv->from->format));
152 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLERATE_IN,
153 conv->from->samplerate);
155 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_CHANNELS_IN,
156 conv->from->channels);
157
159 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLEFMT_OUT,
160 xmms_sample_name_get (conv->to->format));
162 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_SAMPLERATE_OUT,
163 conv->to->samplerate);
165 XMMS_MEDIALIB_ENTRY_PROPERTY_FMT_CHANNELS_OUT,
166 conv->to->channels);
167
168 xmms_medialib_end (session);
169#endif
170}
171
172
173/**
174 * convert from milliseconds to samples for this format.
175 */
176guint
177xmms_sample_ms_to_samples (const xmms_stream_type_t *st, guint milliseconds)
178{
179 gint rate;
181 return (guint)(((gdouble) rate) * milliseconds / 1000);
182}
183
184/**
185 * Convert from samples to milliseconds for this format
186 */
187guint
189{
190 gint rate;
192 return (guint) (((gdouble)samples) * 1000.0 / rate);
193}
194
195/**
196 * Convert from bytes to milliseconds for this format
197 */
198guint
200{
201 guint samples = bytes / xmms_sample_frame_size_get (st);
202 return xmms_sample_samples_to_ms (st, samples);
203}
204
205gint
207{
208 gint format, channels;
211 return xmms_sample_size_get (format) * channels;
212}
213
214static void
215recalculate_resampler (xmms_sample_converter_t *conv, guint from, guint to)
216{
217 guint a,b;
218
219 /* calculate ratio */
220 if (from > to){
221 a = from;
222 b = to;
223 } else {
224 b = to;
225 a = from;
226 }
227
228 while (b != 0) { /* good 'ol euclid is helpful as usual */
229 guint t = a % b;
230 a = b;
231 b = t;
232 }
233
234 XMMS_DBG ("Resampling ratio: %d:%d",
235 from / a, to / a);
236
237 conv->interpolator_ratio = to/a;
238 conv->decimator_ratio = from/a;
239
240 conv->state = g_malloc0 (xmms_sample_frame_size_get (conv->from));
241
242 /*
243 * calculate filter here
244 *
245 * We don't use no stinkning filter. Maybe we should,
246 * but I'm deaf anyway, I wont hear any difference.
247 */
248
249}
250
251
252/**
253 * do the actual converstion between two audio formats.
254 */
255void
256xmms_sample_convert (xmms_sample_converter_t *conv, xmms_sample_t *in, guint len, xmms_sample_t **out, guint *outlen)
257{
258 int inusiz, outusiz;
259 int olen;
260 guint res;
261
262 inusiz = xmms_sample_frame_size_get (conv->from);
263
264 g_return_if_fail (len % inusiz == 0);
265
266 if (conv->same) {
267 *outlen = len;
268 *out = in;
269 return;
270 }
271
272 len /= inusiz;
273
274 outusiz = xmms_sample_frame_size_get (conv->to);
275
276 if (conv->resample) {
277 olen = (len * conv->interpolator_ratio / conv->decimator_ratio) * outusiz + outusiz;
278 } else {
279 olen = len * outusiz;
280 }
281 if (olen > conv->bufsiz) {
282 void *t;
283 t = g_realloc (conv->buf, olen);
284 g_assert (t); /* XXX */
285 conv->buf = t;
286 conv->bufsiz = olen;
287 }
288
289 res = conv->func (conv, in, len, conv->buf);
290
291 *outlen = res * outusiz;
292 *out = conv->buf;
293
294}
295
296gint64
298{
299 /* this isn't 100% accurate, we should take care
300 of rounding here and set conv->offset, but noone
301 will notice, except when reading this comment :) */
302
303 if (!conv->resample)
304 return samples;
305 return samples * conv->decimator_ratio / conv->interpolator_ratio;
306}
307
308gint64
310{
311 if (!conv->resample)
312 return samples;
313 return samples * conv->interpolator_ratio / conv->decimator_ratio;
314}
315
316void
318{
319 if (conv->resample) {
320 conv->offset = 0;
321 memset (conv->state, 0, xmms_sample_frame_size_get (conv->from));
322 }
323}
324
325/**
326 * @}
327 */
gboolean xmms_medialib_entry_property_set_str(xmms_medialib_session_t *session, xmms_medialib_entry_t entry, const gchar *property, const gchar *value)
Set a entry property to a new value, overwriting the old value.
Definition: medialib.c:621
gboolean xmms_medialib_entry_property_set_int(xmms_medialib_session_t *session, xmms_medialib_entry_t entry, const gchar *property, gint value)
Set a entry property to a new value, overwriting the old value.
Definition: medialib.c:571
void xmms_medialib_end(xmms_medialib_session_t *session)
Definition: medialib.c:425
xmms_stream_type_t * xmms_sample_converter_get_from(xmms_sample_converter_t *conv)
Return the audio format used by the converter as source.
Definition: sample.head.c:121
gint64 xmms_sample_convert_scale(xmms_sample_converter_t *conv, gint64 samples)
Definition: sample.head.c:297
gint xmms_sample_frame_size_get(const xmms_stream_type_t *st)
Definition: sample.head.c:206
void xmms_sample_convert_reset(xmms_sample_converter_t *conv)
Definition: sample.head.c:317
void xmms_sample_convert(xmms_sample_converter_t *conv, xmms_sample_t *in, guint len, xmms_sample_t **out, guint *outlen)
do the actual converstion between two audio formats.
Definition: sample.head.c:256
xmms_sample_converter_t * xmms_sample_converter_init(xmms_stream_type_t *from, xmms_stream_type_t *to)
Definition: sample.head.c:77
gint64 xmms_sample_convert_rev_scale(xmms_sample_converter_t *conv, gint64 samples)
Definition: sample.head.c:309
xmms_stream_type_t * xmms_sample_converter_get_to(xmms_sample_converter_t *conv)
Return the audio format used by the converter as target.
Definition: sample.head.c:132
guint xmms_sample_bytes_to_ms(const xmms_stream_type_t *st, guint bytes)
Convert from bytes to milliseconds for this format.
Definition: sample.head.c:199
void xmms_sample_converter_to_medialib(xmms_sample_converter_t *conv, xmms_medialib_entry_t entry)
Definition: sample.head.c:142
guint xmms_sample_ms_to_samples(const xmms_stream_type_t *st, guint milliseconds)
convert from milliseconds to samples for this format.
Definition: sample.head.c:177
guint xmms_sample_samples_to_ms(const xmms_stream_type_t *st, guint samples)
Convert from samples to milliseconds for this format.
Definition: sample.head.c:188
guint(* xmms_sample_conv_func_t)(xmms_sample_converter_t *, xmms_sample_t *, guint, xmms_sample_t *)
Definition: xmms_sample.h:24
gint xmms_stream_type_get_int(const xmms_stream_type_t *st, xmms_stream_type_key_t key)
Definition: streamtype.c:171
#define xmms_log_error(fmt,...)
Definition: xmms_log.h:35
#define XMMS_DBG(fmt,...)
Definition: xmms_log.h:32
#define xmms_medialib_begin_write()
struct xmms_medialib_session_St xmms_medialib_session_t
Definition: xmms_medialib.h:87
G_BEGIN_DECLS typedef gint32 xmms_medialib_entry_t
Definition: xmms_medialib.h:86
void xmms_sample_t
Definition: xmms_sample.h:58
struct xmms_sample_converter_St xmms_sample_converter_t
Definition: xmms_sample.h:38
xmms_sample_format_t
Definition: xmms_sample.h:25
@ XMMS_STREAM_TYPE_FMT_FORMAT
@ XMMS_STREAM_TYPE_FMT_SAMPLERATE
@ XMMS_STREAM_TYPE_FMT_CHANNELS
struct xmms_stream_type_St xmms_stream_type_t
#define xmms_object_new(objtype, destroyfunc)
Definition: xmms_object.h:115
#define xmms_object_unref(obj)
Definition: xmms_object.h:109