summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2002-10-24 17:51:30 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2002-10-24 17:51:30 +0000
commitaaf25c79cff81c8b9fc31554b4e3a325c0af2803 (patch)
tree41c1409b85490cb490c91cb3cc215c2907a2a28c
parent7b3b35c3616e4de1eaa85afd72237cb35f9c82a5 (diff)
downloadxine-lib-aaf25c79cff81c8b9fc31554b4e3a325c0af2803.tar.gz
xine-lib-aaf25c79cff81c8b9fc31554b4e3a325c0af2803.tar.bz2
fix identiation, implement an audio compressor filter (yeah, i know a big concept for audio filter plugins is needed but sorry, this has been on my todo-list for too long)
CVS patchset: 2990 CVS date: 2002/10/24 17:51:30
-rw-r--r--src/xine-engine/audio_out.c327
-rw-r--r--src/xine-engine/audio_out.h7
2 files changed, 207 insertions, 127 deletions
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index ad5f5ad5a..0c7310557 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -17,7 +17,7 @@
* along with self program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.c,v 1.73 2002/10/20 15:56:27 guenter Exp $
+ * $Id: audio_out.c,v 1.74 2002/10/24 17:51:30 guenter Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -26,14 +26,18 @@
*
* General Programming Guidelines: -
* New concept of an "audio_frame".
- * An audio_frame consists of all the samples required to fill every audio channel to a full amount of bits.
- * So, it does not mater how many bits per sample, or how many audio channels are being used, the number of audio_frames is the same.
+ * An audio_frame consists of all the samples required to fill every
+ * audio channel to a full amount of bits.
+ * So, it does not mater how many bits per sample, or how many audio channels
+ * are being used, the number of audio_frames is the same.
* E.g. 16 bit stereo is 4 bytes, but one frame.
* 16 bit 5.1 surround is 12 bytes, but one frame.
- * The purpose of this is to make the audio_sync code a lot more readable, rather than having to multiply by the amount of channels all the time
+ * The purpose of this is to make the audio_sync code a lot more readable,
+ * rather than having to multiply by the amount of channels all the time
* when dealing with audio_bytes instead of audio_frames.
*
- * The number of samples passed to/from the audio driver is also sent in units of audio_frames.
+ * The number of samples passed to/from the audio driver is also sent
+ * in units of audio_frames.
*
* Currently, James has tested with OSS: Standard stereo out, SPDIF PCM, SPDIF AC3
* ALSA: Standard stereo out
@@ -270,135 +274,185 @@ static audio_buffer_t * swap_frame_buffers ( ao_instance_t *this ) {
static int mode_channels( int mode ) {
switch( mode ) {
- case AO_CAP_MODE_MONO:
- return 1;
- case AO_CAP_MODE_STEREO:
- return 2;
- case AO_CAP_MODE_4CHANNEL:
- return 4;
- case AO_CAP_MODE_5CHANNEL:
- return 5;
- case AO_CAP_MODE_5_1CHANNEL:
- return 6;
+ case AO_CAP_MODE_MONO:
+ return 1;
+ case AO_CAP_MODE_STEREO:
+ return 2;
+ case AO_CAP_MODE_4CHANNEL:
+ return 4;
+ case AO_CAP_MODE_5CHANNEL:
+ return 5;
+ case AO_CAP_MODE_5_1CHANNEL:
+ return 6;
}
return 0;
}
+static void audio_filter_compress (ao_instance_t *this, int16_t *mem, int num_frames) {
+
+ int i, maxs;
+ double f_max;
+ int num_channels;
+
+ num_channels = mode_channels (this->input.mode);
+ if (!num_channels)
+ return;
+
+ maxs = 0;
+
+ /* measure */
+
+ for (i=0; i<num_frames*num_channels; i++) {
+ int16_t sample = abs(mem[i]);
+ if (sample>maxs)
+ maxs = sample;
+ }
+
+ /* calc maximum possible & allowed factor */
+
+ if (maxs>0) {
+ f_max = 32767.0 / maxs;
+ this->compression_factor = this->compression_factor * 0.999 + f_max * 0.001;
+ if (this->compression_factor > f_max)
+ this->compression_factor = f_max;
+
+ if (this->compression_factor > this->compression_factor_max)
+ this->compression_factor = this->compression_factor_max;
+ }
+
+#if LOG
+ printf ("audio_out: max=%d f_max=%f compression_factor=%f\n",
+ maxs, f_max, this->compression_factor);
+#endif
+
+ /* apply it */
+
+ for (i=0; i<num_frames*num_channels; i++)
+ mem [i] = mem[i] * this->compression_factor;
+}
+
static audio_buffer_t* prepare_samples( ao_instance_t *this, audio_buffer_t *buf) {
double acc_output_frames, output_frame_excess = 0;
int num_output_frames ;
- /*
- * resample and output audio data
- */
+ /*
+ * volume / compressor filter
+ */
+
+ if ( this->do_compress && (this->input.bits == 16))
+ audio_filter_compress (this, buf->mem, buf->num_frames);
- /* calculate number of output frames (after resampling) */
- acc_output_frames = (double) buf->num_frames * this->frame_rate_factor
- + output_frame_excess;
+ /*
+ * resample and output audio data
+ */
- /* Truncate to an integer */
- num_output_frames = acc_output_frames;
+ /* calculate number of output frames (after resampling) */
+ acc_output_frames = (double) buf->num_frames * this->frame_rate_factor
+ + output_frame_excess;
- /* Keep track of the amount truncated */
- output_frame_excess = acc_output_frames - (double) num_output_frames;
+ /* Truncate to an integer */
+ num_output_frames = acc_output_frames;
+
+ /* Keep track of the amount truncated */
+ output_frame_excess = acc_output_frames - (double) num_output_frames;
#ifdef LOG
- printf ("audio_out: outputting %d frames\n", num_output_frames);
+ printf ("audio_out: outputting %d frames\n", num_output_frames);
#endif
- /* convert 8 bit samples as needed */
- if( this->input.bits == 8 &&
- (this->do_resample || this->output.bits != 8 ||
- this->input.mode != this->output.mode ) ) {
- ensure_buffer_size(this->frame_buf[1], 2*mode_channels(this->input.mode),
- buf->num_frames );
- audio_out_resample_8to16((int8_t *)buf->mem, this->frame_buf[1]->mem,
- mode_channels(this->input.mode) * buf->num_frames );
- buf = swap_frame_buffers(this);
- }
+ /* convert 8 bit samples as needed */
+ if( this->input.bits == 8 &&
+ (this->do_resample || this->output.bits != 8 ||
+ this->input.mode != this->output.mode ) ) {
+ ensure_buffer_size(this->frame_buf[1], 2*mode_channels(this->input.mode),
+ buf->num_frames );
+ audio_out_resample_8to16((int8_t *)buf->mem, this->frame_buf[1]->mem,
+ mode_channels(this->input.mode) * buf->num_frames );
+ buf = swap_frame_buffers(this);
+ }
- /* check if resampling may be skipped */
- if ( this->do_resample &&
- buf->num_frames != num_output_frames ) {
- switch (this->input.mode) {
- case AO_CAP_MODE_MONO:
- ensure_buffer_size(this->frame_buf[1], 2, num_output_frames);
- audio_out_resample_mono (buf->mem, buf->num_frames,
- this->frame_buf[1]->mem, num_output_frames);
- buf = swap_frame_buffers(this);
- break;
- case AO_CAP_MODE_STEREO:
- ensure_buffer_size(this->frame_buf[1], 4, num_output_frames);
- audio_out_resample_stereo (buf->mem, buf->num_frames,
- this->frame_buf[1]->mem, num_output_frames);
- buf = swap_frame_buffers(this);
- break;
- case AO_CAP_MODE_4CHANNEL:
- ensure_buffer_size(this->frame_buf[1], 8, num_output_frames);
- audio_out_resample_4channel (buf->mem, buf->num_frames,
- this->frame_buf[1]->mem, num_output_frames);
- buf = swap_frame_buffers(this);
- break;
- case AO_CAP_MODE_5CHANNEL:
- ensure_buffer_size(this->frame_buf[1], 10, num_output_frames);
- audio_out_resample_5channel (buf->mem, buf->num_frames,
- this->frame_buf[1]->mem, num_output_frames);
- buf = swap_frame_buffers(this);
- break;
- case AO_CAP_MODE_5_1CHANNEL:
- ensure_buffer_size(this->frame_buf[1], 12, num_output_frames);
- audio_out_resample_6channel (buf->mem, buf->num_frames,
- this->frame_buf[1]->mem, num_output_frames);
- buf = swap_frame_buffers(this);
- break;
- case AO_CAP_MODE_A52:
- case AO_CAP_MODE_AC5:
- /* pass-through modes: no resampling */
- break;
- }
- }
+ /* check if resampling may be skipped */
+ if ( this->do_resample &&
+ buf->num_frames != num_output_frames ) {
+ switch (this->input.mode) {
+ case AO_CAP_MODE_MONO:
+ ensure_buffer_size(this->frame_buf[1], 2, num_output_frames);
+ audio_out_resample_mono (buf->mem, buf->num_frames,
+ this->frame_buf[1]->mem, num_output_frames);
+ buf = swap_frame_buffers(this);
+ break;
+ case AO_CAP_MODE_STEREO:
+ ensure_buffer_size(this->frame_buf[1], 4, num_output_frames);
+ audio_out_resample_stereo (buf->mem, buf->num_frames,
+ this->frame_buf[1]->mem, num_output_frames);
+ buf = swap_frame_buffers(this);
+ break;
+ case AO_CAP_MODE_4CHANNEL:
+ ensure_buffer_size(this->frame_buf[1], 8, num_output_frames);
+ audio_out_resample_4channel (buf->mem, buf->num_frames,
+ this->frame_buf[1]->mem, num_output_frames);
+ buf = swap_frame_buffers(this);
+ break;
+ case AO_CAP_MODE_5CHANNEL:
+ ensure_buffer_size(this->frame_buf[1], 10, num_output_frames);
+ audio_out_resample_5channel (buf->mem, buf->num_frames,
+ this->frame_buf[1]->mem, num_output_frames);
+ buf = swap_frame_buffers(this);
+ break;
+ case AO_CAP_MODE_5_1CHANNEL:
+ ensure_buffer_size(this->frame_buf[1], 12, num_output_frames);
+ audio_out_resample_6channel (buf->mem, buf->num_frames,
+ this->frame_buf[1]->mem, num_output_frames);
+ buf = swap_frame_buffers(this);
+ break;
+ case AO_CAP_MODE_A52:
+ case AO_CAP_MODE_AC5:
+ /* pass-through modes: no resampling */
+ break;
+ }
+ }
- /* mode conversion */
- if ( this->input.mode != this->output.mode ) {
- switch (this->input.mode) {
- case AO_CAP_MODE_MONO:
- if( this->output.mode == AO_CAP_MODE_STEREO ) {
- ensure_buffer_size(this->frame_buf[1], 4, buf->num_frames );
- audio_out_resample_monotostereo(buf->mem, this->frame_buf[1]->mem,
- buf->num_frames );
- buf = swap_frame_buffers(this);
- }
- break;
- case AO_CAP_MODE_STEREO:
- if( this->output.mode == AO_CAP_MODE_MONO ) {
- ensure_buffer_size(this->frame_buf[1], 2, buf->num_frames );
- audio_out_resample_stereotomono(buf->mem, this->frame_buf[1]->mem,
- buf->num_frames );
- buf = swap_frame_buffers(this);
- }
- break;
- case AO_CAP_MODE_4CHANNEL:
- break;
- case AO_CAP_MODE_5CHANNEL:
- break;
- case AO_CAP_MODE_5_1CHANNEL:
- break;
- case AO_CAP_MODE_A52:
- case AO_CAP_MODE_AC5:
- break;
- }
+ /* mode conversion */
+ if ( this->input.mode != this->output.mode ) {
+ switch (this->input.mode) {
+ case AO_CAP_MODE_MONO:
+ if( this->output.mode == AO_CAP_MODE_STEREO ) {
+ ensure_buffer_size(this->frame_buf[1], 4, buf->num_frames );
+ audio_out_resample_monotostereo(buf->mem, this->frame_buf[1]->mem,
+ buf->num_frames );
+ buf = swap_frame_buffers(this);
}
-
- /* convert back to 8 bits after resampling */
- if( this->output.bits == 8 && (this->do_resample ||
- this->input.mode != this->output.mode) ) {
- ensure_buffer_size(this->frame_buf[1], 1*mode_channels(this->output.mode),
- buf->num_frames );
- audio_out_resample_16to8(buf->mem, (int8_t *)this->frame_buf[1]->mem,
- mode_channels(this->output.mode) * buf->num_frames );
- buf = swap_frame_buffers(this);
+ break;
+ case AO_CAP_MODE_STEREO:
+ if( this->output.mode == AO_CAP_MODE_MONO ) {
+ ensure_buffer_size(this->frame_buf[1], 2, buf->num_frames );
+ audio_out_resample_stereotomono(buf->mem, this->frame_buf[1]->mem,
+ buf->num_frames );
+ buf = swap_frame_buffers(this);
}
-return buf;
+ break;
+ case AO_CAP_MODE_4CHANNEL:
+ break;
+ case AO_CAP_MODE_5CHANNEL:
+ break;
+ case AO_CAP_MODE_5_1CHANNEL:
+ break;
+ case AO_CAP_MODE_A52:
+ case AO_CAP_MODE_AC5:
+ break;
+ }
+ }
+
+ /* convert back to 8 bits after resampling */
+ if( this->output.bits == 8 && (this->do_resample ||
+ this->input.mode != this->output.mode) ) {
+ ensure_buffer_size(this->frame_buf[1], 1*mode_channels(this->output.mode),
+ buf->num_frames );
+ audio_out_resample_16to8(buf->mem, (int8_t *)this->frame_buf[1]->mem,
+ mode_channels(this->output.mode) * buf->num_frames );
+ buf = swap_frame_buffers(this);
+ }
+ return buf;
}
@@ -417,11 +471,11 @@ static void *ao_loop (void *this_gen) {
int64_t gap;
int64_t delay;
int64_t cur_time;
- int num_output_frames ;
- int paused_wait;
+ /* int num_output_frames ;*/
+ /* int paused_wait; */
int64_t last_sync_time;
int bufs_since_sync;
- double acc_output_frames, output_frame_excess = 0;
+ /* double acc_output_frames, output_frame_excess = 0; */
last_sync_time = bufs_since_sync = 0;
#ifdef LOG
@@ -851,20 +905,37 @@ static uint32_t ao_get_capabilities (ao_instance_t *this) {
static int ao_get_property (ao_instance_t *this, int property) {
int ret;
- pthread_mutex_lock( &this->driver_lock );
- ret = this->driver->get_property(this->driver, property);
- pthread_mutex_unlock( &this->driver_lock );
-
+ switch (property) {
+ case AO_PROP_COMPRESSOR:
+ ret = this->compression_factor_max*100;
+ break;
+
+ default:
+ pthread_mutex_lock( &this->driver_lock );
+ ret = this->driver->get_property(this->driver, property);
+ pthread_mutex_unlock( &this->driver_lock );
+ }
return ret;
}
static int ao_set_property (ao_instance_t *this, int property, int value) {
int ret;
- pthread_mutex_lock( &this->driver_lock );
- ret = this->driver->set_property(this->driver, property, value);
- pthread_mutex_unlock( &this->driver_lock );
-
+ switch (property) {
+ case AO_PROP_COMPRESSOR:
+
+ this->compression_factor_max = (double) value / 100.0;
+ this->do_compress = (this->compression_factor_max >1.0);
+
+ ret = this->compression_factor_max*100;
+ break;
+
+ default:
+ pthread_mutex_lock( &this->driver_lock );
+ ret = this->driver->set_property(this->driver, property, value);
+ pthread_mutex_unlock( &this->driver_lock );
+ }
+
return ret;
}
@@ -928,6 +999,10 @@ ao_instance_t *ao_new_instance (xine_ao_driver_t *driver,
_("adjust if audio is offsync"),
NULL, 10, NULL, NULL);
+ this->compression_factor = 1.0;
+ this->compression_factor_max = 4.0;
+ this->do_compress = 0;
+
/*
* pre-allocate memory for samples
*/
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index c3d7d1090..b22f1a7bc 100644
--- a/src/xine-engine/audio_out.h
+++ b/src/xine-engine/audio_out.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.h,v 1.38 2002/10/17 17:43:44 mroi Exp $
+ * $Id: audio_out.h,v 1.39 2002/10/24 17:51:30 guenter Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -232,6 +232,10 @@ struct ao_instance_s {
int16_t *zero_space;
int64_t passthrough_offset;
+
+ int do_compress;
+ double compression_factor; /* current compression */
+ double compression_factor_max; /* user limit on compression */
};
typedef struct audio_driver_class_s audio_driver_class_t;
@@ -294,6 +298,7 @@ ao_instance_t *ao_new_instance (xine_ao_driver_t *driver,
#define AO_PROP_MIXER_VOL 0
#define AO_PROP_PCM_VOL 1
#define AO_PROP_MUTE_VOL 2
+#define AO_PROP_COMPRESSOR 3
/* audio device control ops */