You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
910 lines
28 KiB
910 lines
28 KiB
/* GSL - Generic Sound Layer
|
|
* Copyright (C) 2001-2002 Stefan Westerfeld and Tim Janik
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General
|
|
* Public License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
#ifndef __GSL_DATA_UTILS_H__
|
|
#define __GSL_DATA_UTILS_H__
|
|
|
|
#include <gsl/gslmath.h>
|
|
#include <gsl/gsldatahandle.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
/* --- structures --- */
|
|
#define GSL_DATA_HANDLE_PEEK_BUFFER (8192)
|
|
typedef struct
|
|
{
|
|
gint dir; /* initialize direction to -1 or +1 (or 0 for random access) */
|
|
GslLong start; /* initialize to 0 */
|
|
GslLong end; /* initialize to 0 */
|
|
gfloat data[GSL_DATA_HANDLE_PEEK_BUFFER];
|
|
} GslDataPeekBuffer;
|
|
typedef struct
|
|
{
|
|
GslLong head_skip; /* FIXME: remove this */
|
|
GslLong tail_cut;
|
|
GslLong min_loop;
|
|
GslLong max_loop;
|
|
} GslLoopSpec; /* rename this to ...Data... */
|
|
|
|
|
|
/* --- data utils --- */
|
|
gboolean gsl_data_detect_signal (GslDataHandle *handle,
|
|
GslLong *sigstart,
|
|
GslLong *sigend);
|
|
GslLong gsl_data_find_sample (GslDataHandle *dhandle,
|
|
gfloat min_value,
|
|
gfloat max_value,
|
|
GslLong start_offset,
|
|
gint direction);
|
|
gboolean gsl_data_find_tailmatch (GslDataHandle *dhandle,
|
|
const GslLoopSpec *lspec,
|
|
GslLong *loop_start_p,
|
|
GslLong *loop_end_p);
|
|
GslLong gsl_data_find_block (GslDataHandle *handle,
|
|
guint n_values,
|
|
const gfloat *values,
|
|
gfloat epsilon);
|
|
|
|
|
|
/* --- data handle utils --- */
|
|
static inline gfloat gsl_data_handle_peek_value (GslDataHandle *dhandle,
|
|
GslLong position,
|
|
GslDataPeekBuffer *peekbuf);
|
|
gint /* errno */ gsl_data_handle_dump (GslDataHandle *dhandle,
|
|
gint fd,
|
|
GslWaveFormatType format,
|
|
guint byte_order);
|
|
gint /* errno */ gsl_data_handle_dump_wav (GslDataHandle *dhandle,
|
|
gint fd,
|
|
guint n_bits,
|
|
guint n_channels,
|
|
guint sample_freq);
|
|
|
|
|
|
/* --- conversion utils --- */
|
|
static inline guint gsl_conv_from_float (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gfloat *src,
|
|
gpointer dest,
|
|
guint n_values);
|
|
static inline guint gsl_conv_from_float_clip (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gfloat *src,
|
|
gpointer dest,
|
|
guint n_values);
|
|
static inline void gsl_conv_to_float (GslWaveFormatType format,
|
|
guint byte_order,
|
|
gconstpointer src,
|
|
gfloat *dest,
|
|
guint n_values);
|
|
static inline guint gsl_conv_from_double (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gdouble *src,
|
|
gpointer dest,
|
|
guint n_values);
|
|
static inline guint gsl_conv_from_double_clip (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gdouble *src,
|
|
gpointer dest,
|
|
guint n_values);
|
|
static inline void gsl_conv_to_double (GslWaveFormatType format,
|
|
guint byte_order,
|
|
gconstpointer src,
|
|
gdouble *dest,
|
|
guint n_values);
|
|
|
|
|
|
|
|
/* --- misc implementations --- */
|
|
gfloat gsl_data_peek_value_f (GslDataHandle *dhandle,
|
|
GslLong pos,
|
|
GslDataPeekBuffer *peekbuf);
|
|
|
|
static inline gfloat
|
|
gsl_data_handle_peek_value (GslDataHandle *dhandle,
|
|
GslLong position,
|
|
GslDataPeekBuffer *peekbuf)
|
|
{
|
|
return (position >= peekbuf->start && position < peekbuf->end ?
|
|
peekbuf->data[position - peekbuf->start] :
|
|
gsl_data_peek_value_f (dhandle, position, peekbuf));
|
|
}
|
|
|
|
#define GSL_CONV_FORMAT(format, endian_flag) (((endian_flag) << 16) | ((format) & 0xffff))
|
|
|
|
static inline guint /* returns number of bytes used in dest */
|
|
gsl_conv_from_float (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gfloat *src,
|
|
gpointer dest,
|
|
guint n_values)
|
|
{
|
|
gint8 *i8 = (gint8*) dest;
|
|
guint8 *u8 = (guint8*) dest;
|
|
gint16 *i16 = (gint16*) dest;
|
|
guint16 *u16 = (guint16*) dest;
|
|
guint32 *u32dest = (guint32*) dest;
|
|
const gfloat *bound = src + n_values;
|
|
guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
|
|
|
|
if (!n_values)
|
|
return 0;
|
|
|
|
switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
|
|
{
|
|
GslFpuState fpu;
|
|
gfloat v;
|
|
gint16 vi16;
|
|
guint16 vu16;
|
|
guint32 vu32;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
*u8++ = *src++ * 128. + 128.5;
|
|
while (src < bound);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 128.;
|
|
*i8++ = gsl_ftoi (v);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*u16++ = *src++ * 2048. + 2048.5;
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *src++ * 2048. + 2048.5;
|
|
*u16++ = GUINT16_SWAP_LE_BE (vu16);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
*i16++ = gsl_ftoi (v);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
vi16 = gsl_ftoi (v);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi16);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*u16++ = *src++ * 32768. + 32768.5;
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *src++ * 32768. + 32768.5;
|
|
*u16++ = GUINT16_SWAP_LE_BE (vu16);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
*i16++ = gsl_ftoi (v);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
vi16 = gsl_ftoi (v);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi16);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
return n_values << 2;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu32 = *u32src++;
|
|
*u32dest++ = GUINT32_SWAP_LE_BE (vu32);
|
|
}
|
|
while (u32src < u32bound);
|
|
return n_values << 2;
|
|
default:
|
|
g_assert_not_reached ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static inline guint /* returns number of bytes used in dest */
|
|
gsl_conv_from_float_clip (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gfloat *src,
|
|
gpointer dest,
|
|
guint n_values)
|
|
{
|
|
gint8 *i8 = (gint8*) dest;
|
|
guint8 *u8 = (guint8*) dest;
|
|
gint16 *i16 = (gint16*) dest;
|
|
guint16 *u16 = (guint16*) dest;
|
|
guint32 *u32dest = (guint32*) dest;
|
|
const gfloat *bound = src + n_values;
|
|
guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
|
|
|
|
if (!n_values)
|
|
return 0;
|
|
|
|
switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
|
|
{
|
|
GslFpuState fpu;
|
|
gfloat v;
|
|
guint32 vu32;
|
|
gint32 vi32;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 128. + 128.5;
|
|
*u8++ = CLAMP (vi32, 0, 255);
|
|
}
|
|
while (src < bound);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 128.;
|
|
vi32 = gsl_ftoi (v);
|
|
*i8++ = CLAMP (vi32, -128, 127);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 2048. + 2048.5;
|
|
*u16++ = CLAMP (vi32, 0, 4095);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 2048. + 2048.5;
|
|
vi32 = CLAMP (vi32, 0, 4095);
|
|
*u16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
vi32 = gsl_ftoi (v);
|
|
*i16++ = CLAMP (vi32, -2048, 2047);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
vi32 = gsl_ftoi (v);
|
|
vi32 = CLAMP (vi32, -2048, 2047);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 32768. + 32768.5;
|
|
*u16++ = CLAMP (vi32, 0, 65535);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 32768. + 32768.5;
|
|
vi32 = CLAMP (vi32, 0, 65535);
|
|
*u16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
vi32 = gsl_ftoi (v);
|
|
vi32 = CLAMP (vi32, -32768, 32767);
|
|
*i16++ = vi32;
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
vi32 = gsl_ftoi (v);
|
|
vi32 = CLAMP (vi32, -32768, 32767);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
return n_values << 2;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu32 = *u32src++;
|
|
*u32dest++ = GUINT32_SWAP_LE_BE (vu32);
|
|
}
|
|
while (u32src < u32bound);
|
|
return n_values << 2;
|
|
default:
|
|
g_assert_not_reached ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
gsl_conv_to_float (GslWaveFormatType format,
|
|
guint byte_order,
|
|
gconstpointer src,
|
|
gfloat *dest,
|
|
guint n_values)
|
|
{
|
|
guint8 *u8 = (guint8*) src;
|
|
gint8 *i8 = (gint8*) src;
|
|
guint16 *u16 = (guint16*) src;
|
|
gint16 *i16 = (gint16*) src;
|
|
guint32 *u32src = (guint32*) src;
|
|
gfloat *bound = dest + n_values;
|
|
guint32 *u32dest = (guint32*) dest, *u32bound = (guint32*) bound;
|
|
|
|
if (!n_values)
|
|
return;
|
|
|
|
switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
|
|
{
|
|
gint16 vi16;
|
|
guint16 vu16;
|
|
guint32 vu32;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
*dest++ = (*u8++ - 128) * (1. / 128.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
*dest++ = *i8++ * (1. / 128.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*dest++ = ((*u16++ & 0x0fff) - 2048) * (1. / 2048.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *u16++;
|
|
*dest++ = ((GUINT16_SWAP_LE_BE (vu16) & 0x0fff) - 2048) * (1. / 2048.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi16 = *i16++;
|
|
*dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi16 = *i16++;
|
|
vi16 = GUINT16_SWAP_LE_BE (vi16);
|
|
*dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*dest++ = (*u16++ - 32768) * (1. / 32768.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *u16++;
|
|
*dest++ = (GUINT16_SWAP_LE_BE (vu16) - 32768) * (1. / 32768.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*dest++ = *i16++ * (1. / 32768.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi16 = *i16++;
|
|
*dest++ = GUINT16_SWAP_LE_BE (vi16) * (1. / 32768.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu32 = *u32src++;
|
|
*u32dest++ = GUINT32_SWAP_LE_BE (vu32);
|
|
}
|
|
while (u32dest < u32bound);
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
/* same as above with s/float/double */
|
|
static inline guint /* returns number of bytes used in dest */
|
|
gsl_conv_from_double (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gdouble *src,
|
|
gpointer dest,
|
|
guint n_values)
|
|
{
|
|
gint8 *i8 = (gint8*) dest;
|
|
guint8 *u8 = (guint8*) dest;
|
|
gint16 *i16 = (gint16*) dest;
|
|
guint16 *u16 = (guint16*) dest;
|
|
guint32 *u32dest = (guint32*) dest;
|
|
const gdouble *bound = src + n_values;
|
|
guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
|
|
|
|
if (!n_values)
|
|
return 0;
|
|
|
|
switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
|
|
{
|
|
GslFpuState fpu;
|
|
gdouble v;
|
|
gint16 vi16;
|
|
guint16 vu16;
|
|
guint32 vu32;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
*u8++ = *src++ * 128. + 128.5;
|
|
while (src < bound);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 128.;
|
|
*i8++ = gsl_ftoi (v);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*u16++ = *src++ * 2048. + 2048.5;
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *src++ * 2048. + 2048.5;
|
|
*u16++ = GUINT16_SWAP_LE_BE (vu16);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
*i16++ = gsl_ftoi (v);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
vi16 = gsl_ftoi (v);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi16);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*u16++ = *src++ * 32768. + 32768.5;
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *src++ * 32768. + 32768.5;
|
|
*u16++ = GUINT16_SWAP_LE_BE (vu16);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
*i16++ = gsl_ftoi (v);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
vi16 = gsl_ftoi (v);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi16);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
return n_values << 2;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu32 = *u32src++;
|
|
*u32dest++ = GUINT32_SWAP_LE_BE (vu32);
|
|
}
|
|
while (u32src < u32bound);
|
|
return n_values << 2;
|
|
default:
|
|
g_assert_not_reached ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static inline guint /* returns number of bytes used in dest */
|
|
gsl_conv_from_double_clip (GslWaveFormatType format,
|
|
guint byte_order,
|
|
const gdouble *src,
|
|
gpointer dest,
|
|
guint n_values)
|
|
{
|
|
gint8 *i8 = (gint8*) dest;
|
|
guint8 *u8 = (guint8*) dest;
|
|
gint16 *i16 = (gint16*) dest;
|
|
guint16 *u16 = (guint16*) dest;
|
|
guint32 *u32dest = (guint32*) dest;
|
|
const gdouble *bound = src + n_values;
|
|
guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
|
|
|
|
if (!n_values)
|
|
return 0;
|
|
|
|
switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
|
|
{
|
|
GslFpuState fpu;
|
|
gdouble v;
|
|
guint32 vu32;
|
|
gint32 vi32;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 128. + 128.5;
|
|
*u8++ = CLAMP (vi32, 0, 255);
|
|
}
|
|
while (src < bound);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 128.;
|
|
vi32 = gsl_ftoi (v);
|
|
*i8++ = CLAMP (vi32, -128, 127);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 2048. + 2048.5;
|
|
*u16++ = CLAMP (vi32, 0, 4095);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 2048. + 2048.5;
|
|
vi32 = CLAMP (vi32, 0, 4095);
|
|
*u16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
vi32 = gsl_ftoi (v);
|
|
*i16++ = CLAMP (vi32, -2048, 2047);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 2048.;
|
|
vi32 = gsl_ftoi (v);
|
|
vi32 = CLAMP (vi32, -2048, 2047);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 32768. + 32768.5;
|
|
*u16++ = CLAMP (vi32, 0, 65535);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi32 = *src++ * 32768. + 32768.5;
|
|
vi32 = CLAMP (vi32, 0, 65535);
|
|
*u16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
vi32 = gsl_ftoi (v);
|
|
vi32 = CLAMP (vi32, -32768, 32767);
|
|
*i16++ = vi32;
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
gsl_fpu_setround (&fpu);
|
|
do
|
|
{
|
|
v = *src++;
|
|
v *= 32768.;
|
|
vi32 = gsl_ftoi (v);
|
|
vi32 = CLAMP (vi32, -32768, 32767);
|
|
*i16++ = GUINT16_SWAP_LE_BE (vi32);
|
|
}
|
|
while (src < bound);
|
|
gsl_fpu_restore (fpu);
|
|
return n_values << 1;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
return n_values << 2;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu32 = *u32src++;
|
|
*u32dest++ = GUINT32_SWAP_LE_BE (vu32);
|
|
}
|
|
while (u32src < u32bound);
|
|
return n_values << 2;
|
|
default:
|
|
g_assert_not_reached ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
gsl_conv_to_double (GslWaveFormatType format,
|
|
guint byte_order,
|
|
gconstpointer src,
|
|
gdouble *dest,
|
|
guint n_values)
|
|
{
|
|
guint8 *u8 = (guint8*) src;
|
|
gint8 *i8 = (gint8*) src;
|
|
guint16 *u16 = (guint16*) src;
|
|
gint16 *i16 = (gint16*) src;
|
|
guint32 *u32src = (guint32*) src;
|
|
gdouble *bound = dest + n_values;
|
|
guint32 *u32dest = (guint32*) dest, *u32bound = (guint32*) bound;
|
|
|
|
if (!n_values)
|
|
return;
|
|
|
|
switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
|
|
{
|
|
gint16 vi16;
|
|
guint16 vu16;
|
|
guint32 vu32;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
*dest++ = (*u8++ - 128) * (1. / 128.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
*dest++ = *i8++ * (1. / 128.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*dest++ = ((*u16++ & 0x0fff) - 2048) * (1. / 2048.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *u16++;
|
|
*dest++ = ((GUINT16_SWAP_LE_BE (vu16) & 0x0fff) - 2048) * (1. / 2048.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi16 = *i16++;
|
|
*dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi16 = *i16++;
|
|
vi16 = GUINT16_SWAP_LE_BE (vi16);
|
|
*dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*dest++ = (*u16++ - 32768) * (1. / 32768.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu16 = *u16++;
|
|
*dest++ = (GUINT16_SWAP_LE_BE (vu16) - 32768) * (1. / 32768.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
do
|
|
*dest++ = *i16++ * (1. / 32768.);
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vi16 = *i16++;
|
|
*dest++ = GUINT16_SWAP_LE_BE (vi16) * (1. / 32768.);
|
|
}
|
|
while (dest < bound);
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
|
|
break;
|
|
case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
|
|
do
|
|
{
|
|
vu32 = *u32src++;
|
|
*u32dest++ = GUINT32_SWAP_LE_BE (vu32);
|
|
}
|
|
while (u32dest < u32bound);
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#endif /* __GSL_DATA_UTILS_H__ */
|
|
|
|
/* vim:set ts=8 sts=2 sw=2: */
|