?? audio.c
字號:
/*
* FILE: audio.c
* PROGRAM: RAT
* AUTHOR: Orion Hodson
*
* Based on necessity and earlier code by Isidor Kouvelas, Colin
* Perkins, and Orion Hodson. The existence of this code is pretty
* offensive, but it's here for historical reasons.
*
* Copyright (c) 1995-2001 University College London
* All rights reserved.
*/
#ifndef HIDE_SOURCE_STRINGS
static const char cvsid[] =
"$Id: audio.c,v 1.121 2002/03/15 17:57:16 ucacoxh Exp $";
#endif /* HIDE_SOURCE_STRINGS */
#include "config_unix.h"
#include "config_win32.h"
#include "memory.h"
#include "debug.h"
#include "audio_types.h"
#include "codec_types.h"
#include "codec.h"
#include "channel_types.h"
#include "channel.h"
#include "audio.h"
#include "audio_fmt.h"
#include "audio_util.h"
#include "session.h"
#include "transcoder.h"
#include "pdb.h"
#include "transmit.h"
#include "mix.h"
#include "cushion.h"
#include "source.h"
#include "sndfile.h"
#include "tonegen.h"
#include "voxlet.h"
/* Zero buf used for writing zero chunks during cushion adaption */
static sample* zero_buf;
/*****************************************************************************/
/* audio_device_release releases open the device.
* If it succeeds it returns TRUE, otherwise returns FALSE.
*/
int
audio_device_release(session_t *sp, audio_desc_t the_dev)
{
if (sp->audio_device == 0) {
debug_msg("Audio device already released from session\n");
return FALSE;
}
if (sp->audio_device != the_dev) {
debug_msg("Releasing wrong device!\n");
return FALSE;
}
/* Mix is going to be destroyed - tone_generator and
* voxlet have pointers to mixer in their state that
* is about to expire. Could pass mixer as argument
* to their process functions...
*/
if (sp->tone_generator) {
tonegen_destroy(&sp->tone_generator);
}
if (sp->local_file_player) {
voxlet_destroy(&sp->local_file_player);
}
cushion_destroy(&sp->cushion);
mix_destroy(&sp->ms);
tx_stop(sp->tb);
tx_destroy(&sp->tb);
source_list_clear(sp->active_sources);
audio_close(sp->audio_device);
sp->audio_device = 0;
xfree(zero_buf);
zero_buf = NULL;
return FALSE;
}
/* Reconfiguration code ******************************************************/
typedef struct s_audio_config {
audio_desc_t device;
codec_id_t primary;
int render_3d;
} audio_config;
static int
ac_create(audio_config **ppac)
{
audio_config *pac = (audio_config*)xmalloc(sizeof(audio_config));
if (pac) {
/* assign invalid values so easy to see what's change
* in reconfigure. */
pac->device = 0;
pac->primary = 0 ;
pac->render_3d = -1;
*ppac = pac;
return TRUE;
}
return FALSE;
}
static void
ac_destroy(audio_config **ac)
{
assert(ac);
assert(*ac);
xfree(*ac);
*ac = NULL;
}
void
audio_device_register_change_device(struct s_session *sp,
audio_desc_t new_dev)
{
if (sp->new_config == NULL) {
ac_create(&sp->new_config);
}
assert(sp->new_config);
sp->new_config->device = new_dev;
}
void
audio_device_register_change_primary(struct s_session *sp,
codec_id_t primary)
{
if (sp->new_config == NULL) {
ac_create(&sp->new_config);
}
assert(sp->new_config);
sp->new_config->primary = primary;
}
void
audio_device_register_change_render_3d(struct s_session *sp,
int enabled)
{
if (sp->new_config == NULL) {
ac_create(&sp->new_config);
}
assert(sp->new_config);
sp->new_config->render_3d = enabled;
}
static int
audio_device_attempt_config(session_t *sp, audio_config *config)
{
audio_format *inf, *ouf;
const codec_format_t *incf;
int success;
incf = codec_get_format(config->primary);
assert(incf);
inf = audio_format_dup(&incf->format);
ouf = audio_format_dup(&incf->format);
if (inf->channels != 2 && config->render_3d) {
/* If 3d rendering is enabled we need stereo output
* format.
*/
ouf->channels = 2;
}
success = audio_open(config->device, inf, ouf);
if (success) {
mixer_info_t mi;
uint16_t unit_len;
assert(sp->ms == NULL);
assert(sp->tb == NULL);
assert(sp->cushion == NULL);
audio_non_block(config->device);
/* Initialize read and write components */
sp->meter_period = inf->sample_rate / 15;
unit_len = inf->bytes_per_block * 8 / (inf->bits_per_sample*inf->channels);
tx_create(&sp->tb, sp, (uint32_t)inf->sample_rate, (uint16_t)inf->channels, (uint16_t)unit_len);
cushion_create(&sp->cushion, (uint32_t)inf->sample_rate);
sp->cur_ts = ts_convert(inf->sample_rate, sp->cur_ts);
mi.sample_rate = ouf->sample_rate;
mi.channels = ouf->channels;
mi.buffer_length = 32640;
mix_create(&sp->ms, &mi, sp->cur_ts);
if (zero_buf == NULL) {
zero_buf = (sample*)xmalloc(unit_len * sizeof(sample));
audio_zero(zero_buf, unit_len, DEV_S16);
}
}
audio_format_free(&inf);
audio_format_free(&ouf);
return success;
}
/* audio_device_reconfigure returns TRUE if device reconfigured,
* FALSE otherwise
*/
int
audio_device_reconfigure(session_t *sp)
{
audio_config prev_config, *curr_config, *new_config;
audio_port_t iport = 0, oport = 0;
int change_req;
assert(sp->new_config != NULL);
new_config = sp->new_config;
change_req = FALSE;
if (new_config->device == 0) {
/* No request to change audio device */
new_config->device = sp->audio_device;
} else if (new_config->device != sp->audio_device) {
/* Request to change device */
change_req = TRUE;
debug_msg("Change device requested.\n");
}
if (sp->audio_device) {
iport = audio_get_iport(sp->audio_device);
oport = audio_get_oport(sp->audio_device);
}
if (new_config->primary == 0) {
/* No request to change primary encoding */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -