Пример: микшер

Пример исходного кода микшера

#include <example.h>
#include <proto.h>
static uint8_t example_mixer_read( example_t *example, uint32_t reg )
{
uint8_t val = 0;
/* Здесь должен быть код для чтения регистра микшера и установки значения переменной "val". */
return val;
}
static void example_mixer_write( example_t *example, uint32_t reg, uint8_t val )
{
/* Здесь должен быть код для записи в регистр микшера значения переменной.*/
}
static snd_mixer_voice_t stereo_voices[2] = { {SND_MIXER_VOICE_LEFT, 0},
{SND_MIXER_VOICE_RIGHT, 0} };
static struct snd_mixer_element_volume1_range output_range[2] = { {0, 63, -600, 1650},
{0, 63, -600, 1650} };
static struct snd_mixer_element_volume1_range input_range[2] = { {0, 15, -2850, 300},
{0, 15, -2850, 300} };
static int32_t example_master_vol_control( MIXER_CONTEXT_T *example, ado_mixer_delement_t *element, uint8_t set,
uint32_t *vol, void *instance_data )
{
enum example_mixer_reg reg = (int32_t)instance_data;
uint32_t data[2];
int32_t altered = 0;
int max = ado_mixer_element_vol_range_max( element );
data[0] = example_mixer_read( example, reg + 0 );
data[1] = example_mixer_read( example, reg + 2 );
if ( set )
{
altered = vol[0] != (data[0] & max) || vol[1] != (data[1] & max);
data[0] = (data[0] & ~(max)) | vol[0];
data[1] = (data[1] & ~(max)) | vol[0];
example_mixer_write( example, reg + 0, data[0] );
example_mixer_write( example, reg + 2, data[1] );
} else {
vol[0] = (data[0] & max);
vol[1] = (data[1] & max);
}
return (altered);
}
static int32_t example_master_mute_control( MIXER_CONTEXT_T *example, ado_mixer_delement_t *element, uint8_t set,
uint32_t *val, void *instance_data )
{
enum example_mixer_reg reg = (int32_t)instance_data;
uint32_t data[2];
int32_t altered = 0;
data[0] = example_mixer_read( example, reg + 0 );
data[1] = example_mixer_read( example, reg + 2 );
if ( set )
{
altered = val[0] != ((data[0] & 0x40) ? (1 << 0) : 0) |
((data[1] & 0x40) ? (1 << 1) : 0);
data[0] = (data[0] & ~0x40) | ((val[0] & (1 << 0)) ? 0x40 : 0);
data[1] = (data[1] & ~0x40) | ((val[0] & (1 << 1)) ? 0x40 : 0);
example_mixer_write( example, reg + 0, data[0] );
example_mixer_write( example, reg + 2, data[1] );
} else
val[0] = ((data[0] & 0x40) ? (1 << 0) : 0) |
((data[1] & 0x40) ? (1 << 1) : 0);
return (altered);
}
static int32_t example_vol_control( MIXER_CONTEXT_T *example, ado_mixer_delement_t *element, uint8_t set,
uint32_t *vol, void *instance_data )
{
enum example_mixer_reg reg = (int32_t)instance_data;
uint32_t data;
int32_t altered = 0;
int max = ado_mixer_element_vol_range_max( element );
data = example_mixer_read( example, reg );
if ( set )
{
altered = vol[0] != ((data & (max << 8)) >> 8) || vol[1] != (data & max);
data = (data & ~((max << 4) | max)) | ((vol[0]) << 4) | (vol[1]);
example_mixer_write( example, reg, data );
} else {
vol[0] = ((data & (max << 4)) >> 4);
vol[1] = ((data & max));
}
return (altered);
}
int build_in_group( MIXER_CONTEXT_T *example, char *name_p, char *name_c, example_group *grp,
enum example_mixer_reg reg_p, enum example_mixer_reg reg_c )
{
int error = 0;
ado_mixer_delement_t *pre_elem,
*elem = NULL;
char ename[sizeof( ((snd_mixer_eid_t *)0)->name )];
if ( grp == &example->pcm )
{
if ( !error && (elem = ado_mixer_element_io( example->mixer, name_p, SND_MIXER_ETYPE_PLAYBACK1,
0, 2, stereo_voices )) == NULL )
error++;
} else {
if ( !error && (elem = ado_mixer_element_io( example->mixer, name_p, SND_MIXER_ETYPE_INPUT,
0, 2, stereo_voices )) == NULL )
error++;
}
pre_elem = elem;
sprintf( ename, "%s %s", name_p, "Volume" );
if ( !error && (elem = ado_mixer_element_volume1( example->mixer, ename, 2, input_range, example_vol_control,
(void *)reg_p, NULL )) == NULL )
error++;
if ( !error && ado_mixer_element_route_add( example->mixer, pre_elem, elem ) != 0 )
error++;
grp->vol_out = elem;
if ( !error && ado_mixer_element_route_add( example->mixer, elem, example->output_accu ) != 0 )
error++;
if ( name_c )
{
if ( !error && ado_mixer_element_route_add( example->mixer, pre_elem, example->input_accu ) != 0 )
error++;
}
if ( !error && name_p && (grp->group_p = ado_mixer_playback_group_create( example->mixer, name_p, SND_MIXER_CHN_MASK_STEREO,
grp->vol_out, NULL )) == NULL )
error++;
if ( !error && name_c && (grp->group_c = ado_mixer_capture_group_create( example->mixer, name_c, SND_MIXER_CHN_MASK_STEREO,
NULL, NULL, NULL, NULL )) == NULL )
error++;
return (0);
}
int build_example_mixer( MIXER_CONTEXT_T *example, ado_mixer_t *mixer )
{
int error = 0;
ado_mixer_delement_t *pre_elem,
*elem = NULL;
/* ################ */
/* Выходная группа */
/* ################ */
if ( (example->output_accu = ado_mixer_element_accu1( mixer, SND_MIXER_ELEMENT_OUTPUT_ACCU, 0 )) == NULL )
error++;
pre_elem = example->output_accu;
if ( !error && (elem = ado_mixer_element_volume1( mixer, "Output Volume", 2, output_range, example_master_vol_control,
(void *)EXAMPLE_MASTER_LEFT, NULL )) == NULL )
error++;
if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )
error++;
example->master_vol = elem;
pre_elem = elem;
if ( !error && (elem = ado_mixer_element_sw2( mixer, "Output Mute", example_master_mute_control,
(void *)EXAMPLE_MASTER_LEFT, NULL )) == NULL )
error++;
if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )
error++;
example->master_mute = elem;
pre_elem = elem;
if ( !error && (elem = ado_mixer_element_io( mixer, "Output", SND_MIXER_ETYPE_OUTPUT, 0, 2, stereo_voices )) == NULL )
error++;
if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )
error++;
if ( !error && (example->master_grp = ado_mixer_playback_group_create( mixer, SND_MIXER_MASTER_OUT, SND_MIXER_CHN_MASK_STEREO,
example->master_vol, example->master_mute )) == NULL )
error++;
/* ############### */
/* Входная группа*/
/* ############### */
if ( (example->input_accu = ado_mixer_element_accu1( mixer, SND_MIXER_ELEMENT_INPUT_ACCU, 0 )) == NULL )
error++;
pre_elem = example->input_accu;
if ( !error && (elem = ado_mixer_element_volume1( mixer, "Input Volume", 2, input_range, example_vol_control,
(void *)EXAMPLE_RECORD_LEVEL, NULL )) == NULL )
error++;
if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )
error++;
example->master_vol = elem;
pre_elem = elem;
if ( !error && (elem = ado_mixer_element_io( mixer, SND_MIXER_ELEMENT_CAPTURE, SND_MIXER_ETYPE_CAPTURE1, 0, 2,
stereo_voices )) == NULL )
error++;
if ( !error && ado_mixer_element_route_add( mixer, pre_elem, elem ) != 0 )
error++;
if ( !error && (example->input_grp = ado_mixer_capture_group_create( mixer, SND_MIXER_GRP_IGAIN, SND_MIXER_CHN_MASK_STEREO,
example->master_vol, NULL, NULL, NULL )) == NULL )
error++;
/* ################ */
/* Входные группы */
/* ################ */
if ( !error && build_in_group( example, SND_MIXER_PCM_OUT, NULL, &example->pcm, EXAMPLE_PCM_OUT_VOL, NULL ) != 0 )
error++;
if ( !error && build_in_group( example, SND_MIXER_MIC_OUT, SND_MIXER_MIC_IN, &example->mic, EXAMPLE_MIC_OUT_VOL,
EXAMPLE_MIC_IN_VOL ) != 0 )
error++;
if ( !error && build_in_group( example, SND_MIXER_CD_OUT, SND_MIXER_CD_IN, &example->cd, EXAMPLE_CD_OUT_VOL,
EXAMPLE_CD_IN_VOL ) != 0 )
error++;
return (0);
}
ado_mixer_reset_t example_reset;
int example_reset( MIXER_CONTEXT_T *example )
{
/* Эта функция устанаваливает микшер в состояние по умолчанию */
example_mixer_write( example, EXAMPLE_PCM_OUT_VOL, 0xff ); /* Установка громксти PCM на 0% */
example_mixer_write( example, EXAMPLE_CD_OUT_VOL, 0xff ); /* Установка громкости cd на 0% */
example_mixer_write( example, EXAMPLE_REC_SEL, 0x05 ); /* Установка источника записи в микшер */
return (0);
}
ado_mixer_destroy_t example_destroy;
int example_destroy( MIXER_CONTEXT_T *example )
{
/* Эта функция устанавливает микшер в безопасное состояние */
example_mixer_write( example, EXAMPLE_PCM_OUT_VOL, 0x0 ); /* Установка громксти PCM на 0% */
example_mixer_write( example, EXAMPLE_CD_OUT_VOL, 0x00 ); /* Установка громкости cd на 0% */
return (0);
}
int example_mixer( ado_card_t *card, HW_CONTEXT_T *example )
{
int32_t status;
if ( (status = ado_mixer_create( card, "Example", &example->mixer, example )) != EOK )
return (status);
example_mixer_write( example, 0x00, 0x00 ); /* Сброс микшера */
if ( build_example_mixer( example, example->mixer ) )
return (-1);
if ( example_reset( example ) )
return (-1);
/* Следующие функции не являются обязательными, но они должны быть реализованы, если у вас есть действия, которые должны выполняться аппаратным обеспечением
* всякий раз, когда микшер сбрасывается или уничтожается. Эти функции предназначены специально для конкретных требований к оборудованию. */
ado_mixer_set_reset_func( example->mixer, example_reset );
ado_mixer_set_destroy_func( example->mixer, example_destroy );
return (0);
}




Предыдущий раздел: Библиотека libado