⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 会议模拟过程中的混音处理部分,总共包括n+1个声源
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -