📄 sing.c
字号:
{
mprintf( LIGHTGREEN, CONTINUE, "\r\n Audio jukebox mode stopped.\r\n" );
}
}
void audio_sequential_play_control( void )
{
unsigned char result;
if ( is_audio_active() )
return;
mprintf( LIGHTRED, CONTINUE, "\r\n\r\n ********** Audio sequential play mode ********** \r\n" );
mprintf( LIGHTRED, CONTINUE, " (press [j] to quit from ths mode) \r\n\r\n" );
g_seq_play_num = (g_seq_play_num < g_num_of_audio_files) ? g_seq_play_num : 0;
while ( 1 )
{
result = audio_main( g_seq_play_num++ );
if ( !result )
break;
else if ( result == NO_AUDIO_FILE )
continue;
else
{
audio_sequential_play();
break;
}
}
}
/********* *********/
/* */
/* Device class handling functions */
/* */
/* This functions is called from functions in cls_hndl.c as callback */
/* functions. */
/* All these functions are needed to be installed by */
/* "clshndl_initialization_method_install()" in "cls_hndl.c". */
/* */
/* These functions will be called at printer device attach/detach */
/* events. */
/* */
/********* *********/
unsigned short audio_init_commands( device_instance *dvi_ptr )
{
audio_command_vct *commands;
unsigned short vender_id;
unsigned short product_id;
unsigned char target_endpoint;
unsigned short err;
unsigned char i;
if ( devep_regist_config_descriptors( dvi_ptr, 1, 0 ) )
return ( 5 );
if ( g_audio_device_addr != 0 )
{
// Already audio device existing on the USB bus. Do nothing and quit.
return ( 0 );
}
g_audio_buffer = (short *)malloc( sizeof(short) * BUFFER_DEPTH * MEMORY_FILLING_SIZE_FROM_FILE );
g_audio_device_addr = dvi_ptr->address;
if ( NULL == g_audio_buffer )
{
mprintf( LIGHTRED, CONTINUE, "malloc error @ audio_init_commands\r\n" );
return( 2 );
}
for ( i = 0; i < BUFFER_DEPTH; i++ )
g_file_read_buffer_ptr[ i ] = g_audio_buffer + MEMORY_FILLING_SIZE_FROM_FILE * i;
vender_id = (dvi_ptr->dev_descriptor).idVendor;
product_id = (dvi_ptr->dev_descriptor).idProduct;
if ( (vender_id == 0x05FC) && (product_id == 0x7849) )
{
// This is harman/kardon Soundstick
target_endpoint = 1;
for ( i = 0; i < 7; i++ )
if ( 0 != (err = audio_command( dvi_ptr, (g_audio_start_commands_soundstick + i)->com )) )
return ( err );
}
else
{
if ((product_id & 0xFFF0) == AUDIO_CODEC)
commands = g_audio_start_commands_codec;
else if ((product_id & 0xFFF0) == AUDIO_DAC)
commands = g_audio_start_commands_dac;
target_endpoint = 4;
for ( i = 0; i < NUM_OF_AUDIO_COMMANDS; i++ )
if ( 0 != (err = audio_command( dvi_ptr, (commands + i)->com )) )
return ( err );
}
g_iso_ptd0[ 1 ] = (g_iso_ptd0[ 1 ] & 0x0FFF) | (target_endpoint << 12);
g_iso_ptd9[ 1 ] = (g_iso_ptd9[ 1 ] & 0x0FFF) | (target_endpoint << 12);
#ifdef SMALLER_ISO_BUFFER
g_iso_ptdL[ 1 ] = (g_iso_ptdL[ 1 ] & 0x0FFF) | (target_endpoint << 12);
// mprintf( LIGHTRED, CONTINUE, "SMALLER_ISO_BUFFER\r\n" );
#endif //SMALLER_ISO_BUFFER
dvi_ptr->class_instance_ptr = (void *)0x1; // Dummy : To call audio_dispose_process() at device detach
g_previous_audio_state = 1;
{
char s0[ 128 ];
char s1[ 128 ];
unsigned char length0;
unsigned char length1;
unsigned char i;
length0 = (((std_string_descriptor *)(dvi_ptr->string_manufacturer))->bLength) >> 1;
length1 = (((std_string_descriptor *)(dvi_ptr->string_product ))->bLength) >> 1;
ui_unicode_to_C_string( s0, (dvi_ptr->string_manufacturer) + 1, length0 );
ui_unicode_to_C_string( s1, (dvi_ptr->string_product ) + 1, length1 );
if ( (length0 + 1 + length1) >= AUDIO_DEVICE_NAME_STR_LENGTH )
{
length1 = (length1 < AUDIO_DEVICE_NAME_STR_LENGTH) ? length1 : (AUDIO_DEVICE_NAME_STR_LENGTH - 1);
*(s1 + length1) = 0;
sprintf( g_audio_device_name, "(%s)", s1 );
}
else
{
sprintf( g_audio_device_name, "(%s %s)", s0, s1 );
}
for ( i = strlen( g_audio_device_name ); i < (AUDIO_DEVICE_NAME_STR_LENGTH + 2); i++ )
*(g_audio_device_name + i) = ' ';
*(g_audio_device_name + (AUDIO_DEVICE_NAME_STR_LENGTH + 2)) = 0;
}
ui_install_status_monitor_custom_routine( AUDIO_STATUS_MONITOR_LINE, audio_status_monitor );
return ( 0 );
}
unsigned short audio_dispose_process( device_instance *target_device_ptr )
{
device_instance *dvi_ptr;
g_previous_audio_state = NULL;
ui_install_status_monitor_custom_routine( AUDIO_STATUS_MONITOR_LINE, NULL );
free( g_audio_buffer );
g_audio_buffer = NULL;
g_audio_device_addr = 0;
// Search altanative audio device on USB.
(target_device_ptr->interfacef_descriptor).bInterfaceClass = 0xFF; // Modify current device bInterfaceClass first
if ( NULL != (dvi_ptr = devep_find_class_interface( AUDIO_CLASS_INTERFACE, 0 )) )
{
mprintf( LIGHTRED, CONTINUE, "switching audio device\r\n" );
audio_init_commands( dvi_ptr );
}
return ( 0 );
}
static unsigned short audio_command( device_instance *dvi_ptr, unsigned char *com )
{
unsigned short request,
wValue,
wIndex,
wLength;
request = short_swap( *((unsigned short *)(com + 0)) );
wValue = *((unsigned short *)(com + 2));
wIndex = *((unsigned short *)(com + 4));
wLength = *((unsigned short *)(com + 6));
return ( devep_std_request( (com + 8), dvi_ptr, request, wValue, wIndex, &wLength ) );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// New for ISTL control ///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
#ifdef SMALLER_ISO_BUFFER
#define ISTL_TOGGLE_RATE 5 // Toggle rate
#else
#define ISTL_TOGGLE_RATE 10 // Toggle rate
#endif //SMALLER_ISO_BUFFER
#define ISO_START_OFFSET 255 // This must be 255 or less
#define PTD_HEAD_OFFSET 1 // ISTL enabling timing before starting target frame
void audio_start( void )
{
unsigned long start_frame;
unsigned long t_frame;
unsigned char i;
g_audio_quit_timing = 0; // audio play quitting flag
g_audio_abort = False;
isr_install_ISTL_service_routine( NULL ); // Removing ISR for ISTL interrupt
start_frame = isr_get_frame_number() + (ISTL_TOGGLE_RATE << 1);
while ( isr_get_frame_number() < start_frame ) // Wait for previous ISTL data go out
;
sing_buffer_reset(); // Reset the application buffer state
for ( i = 0; i < BUFFER_DEPTH; i++ )
sing_buffer_data_fill(); // Pre-filling application buffer
start_frame = ((isr_get_frame_number() + ISO_START_OFFSET) / ISTL_TOGGLE_RATE) * ISTL_TOGGLE_RATE; // To make frame start ISTL_TOGGLE_RATE*N for debugging easy
iso_buffer_fill( 0, start_frame + ISTL_TOGGLE_RATE ); // Filling ISTL buffer 0
iso_buffer_fill( 1, start_frame + ISTL_TOGGLE_RATE + ISTL_TOGGLE_RATE ); // Filling ISTL buffer 1
gene_install_asynchronous_periodic_process( 0, sing_buffer_data_fill ); // This is to fill application buffer in non-ISR context
while ( (isr_get_frame_number() & 0xFF) != ((start_frame - PTD_HEAD_OFFSET) & 0xFF) ) // Wait for ISTL enabling timing
;
write_register16( Com16_HcISTLToggleRate, ISTL_TOGGLE_RATE ); // Set ISTL toggle rate
isr_install_ISTL_service_routine( iso_transfer_service_from_file_by_ISTL ); // Installing ISR for ISTL interrupt
iso_enable_buffer( 0 ); // Enable ISTL buffer 0
iso_enable_buffer( 1 ); // Enable ISTL buffer 1
g_audio_in_play = True;
}
void audio_stop( void )
{
// write_register16( Com16_HcISTLToggleRate, 0 );
isr_install_ISTL_service_routine( NULL );
g_audio_abort = True;
}
void audio_stop_process( void )
{
gene_install_asynchronous_periodic_process( 0, NULL );
g_buffer_fill_method = NULL;
g_audio_current_target_device_address = 0;
g_audio_in_play = False;
if ( g_stop_process_method )
(*g_stop_process_method)();
g_stop_process_method = NULL;
}
void iso_transfer_service_from_file_by_ISTL( unsigned char buffer_number )
{
unsigned long next_buffer_start_frame;
if ( g_audio_abort )
return;
next_buffer_start_frame = ((isr_get_frame_number() + 1) / ISTL_TOGGLE_RATE) * ISTL_TOGGLE_RATE + ISTL_TOGGLE_RATE;
iso_buffer_fill( buffer_number, next_buffer_start_frame );
iso_enable_buffer( buffer_number );
}
void iso_enable_buffer( unsigned char buffer_number )
{
write_register16( Com16_HcBufferStatus, read_register16( Com16_HcBufferStatus ) | (0x0001 << buffer_number) );
}
void iso_buffer_fill( unsigned char buffer_number, unsigned long frame_count_reference )
{
short *source_buffer;
unsigned short read_size;
unsigned char target_addr;
unsigned char target_port_register;
unsigned short target_buffer_direct_address;
unsigned short packet_size;
unsigned short i;
unsigned char loop_start;
unsigned char loop_lim;
if ( g_audio_abort )
return;
target_addr = g_audio_current_target_device_address;
if ( NULL == devep_find_device( target_addr ) )
{
audio_stop();
return;
}
//
// Fill application buffer for next ISTL buffer filling
//
if ( SING_BUFFER_EMPTY == sing_buffer_stored_length() )
{
if ( (g_audio_source != SOURCE_IS_REMOTE_FILE) && !g_audio_abort && !gp_is_in_DOS_environment )
sing_buffer_data_fill();
else
{
audio_stop();
return;
}
}
//
// Fill ISTL buffer
//
source_buffer = g_file_read_buffer_ptr[ g_file_read_buffer_OUT ];
target_buffer_direct_address = (buffer_number == 0) ? 0 : g_iso_buffer_size;
#ifdef SMALLER_ISO_BUFFER
if ( buffer_number )
{
source_buffer += ((g_audio_packet[ 0 ].size >> 1) * 5);
g_audio_packet[ 4 ].iso_header_ptr = g_iso_ptd9;
loop_start = 5;
loop_lim = 10;
}
else
{
g_audio_packet[ 4 ].iso_header_ptr = g_iso_ptdL;
loop_start = 0;
loop_lim = 5;
}
#else //SMALLER_ISO_BUFFER
loop_start = 0;
loop_lim = ISTL_TOGGLE_RATE;
#endif //SMALLER_ISO_BUFFER
for ( i = loop_start; i < loop_lim; i++ )
{
// copies audio samples with PTD header into ISTL buffer
packet_size = g_audio_packet[ i ].size;
*(g_audio_packet[ i ].iso_header_ptr + 3) = target_addr | 0x00 | (((unsigned short)frame_count_reference++) << 8);
write_direct_access( target_buffer_direct_address, (unsigned char *)(g_audio_packet[ i ].iso_header_ptr), 8 );
target_buffer_direct_address += 8;
// copies PTD data body (audio samples) in to ISTL buffer
write_direct_access( target_buffer_direct_address, (unsigned char *)source_buffer, packet_size );
// update pointers for source and target buffers
source_buffer += (packet_size >> 1); // update source buffer pointer by size of short
target_buffer_direct_address += packet_size; // update target buffer pointer by size of unsigned char
}
#ifdef SMALLER_ISO_BUFFER
if ( !buffer_number )
return;
#endif //SMALLER_ISO_BUFFER
if ( True == g_last_buffer[ g_file_read_buffer_OUT ] )
{
audio_stop();
return;
}
sing_buffer_pointer_increment( &g_file_read_buffer_OUT ); // update application buffer index for OUT
if ( g_file_read_buffer_IN == g_file_read_buffer_OUT ) // if INPUT==OUTPUT after OUTPUT++, that means the application buffer is empty
{
g_sing_buffer_EMPTY = True;
}
}
void sing_buffer_data_fill( void )
{
static unsigned char flag = 0;
if ( flag )
return;
#ifdef SHOW_SING_BUFFER_STATUS
mprintf( WHITE, CONTINUE, "\r\n[out] i=%-2d o=%-2d buffer stat = %-2d %-2d", g_file_read_buffer_IN, g_file_read_buffer_OUT, sing_buffer_stored_length(), g_sing_buffer_EMPTY );
#endif
if ( g_audio_abort )
{
audio_stop_process();
return;
}
if ( SING_BUFFER_FULL == sing_buffer_stored_length() ) // do nothing if the application buffer is full
return;
flag = 1;
sing_buffer_data_read( g_file_read_buffer_ptr[ g_file_read_buffer_IN ] );
sing_buffer_volume_control( g_file_read_buffer_ptr[ g_file_read_buffer_IN ], g_audio_level );
sing_buffer_pointer_increment( &g_file_read_buffer_IN ); // update application buffer index for INPUT
g_sing_buffer_EMPTY = False; // the application buffer is not empty anymore
flag = 0;
}
unsigned short sing_buffer_data_read( short *buffer_ptr )
{
unsigned short (*bf_filling_method)( short *buffer_ptr );
unsigned short read_size;
unsigned short i;
bf_filling_method = g_buffer_fill_method;
if ( bf_filling_method )
read_size = (*bf_filling_method)( buffer_ptr );
else
return ( 0 );
if ( read_size != MEMORY_FILLING_SIZE_FROM_FILE )
{
// gene_install_asynchronous_periodic_process( 0, NULL ); // Stop buffer filling
g_buffer_fill_method = NULL; // Stop buffer filling
g_last_buffer[ g_file_read_buffer_IN ] = True;
for ( i = read_size; i < MEMORY_FILLING_SIZE_FROM_FILE; i++ )
*buffer_ptr++ = 0;
}
return ( read_size ); // size convert from bytes to short
}
unsigned char sing_buffer_stored_length( void )
{
unsigned char in;
unsigned char out;
if ( g_sing_buffer_EMPTY == True )
return ( SING_BUFFER_EMPTY ); // returns value 0 (SING_BUFFER_EMPTY) if it is empty
else
{
in = g_file_read_buffer_IN;
out = g_file_read_buffer_OUT;
if ( in <= out )
in += BUFFER_DEPTH;
return ( in - out ); // returns value from 1 to BUFFER_DEPTH
}
}
void sing_buffer_pointer_increment( unsigned char *v )
{
*v = (*v + 1) & (BUFFER_DEPTH - 1);
}
void sing_buffer_reset( void )
{
unsigned char i;
g_file_read_buffer_IN = 0;
g_file_read_buffer_OUT = 0;
g_audio_quit_timing = 0;
g_sing_buffer_EMPTY = True;
for ( i = 0; i < BUFFER_DEPTH; i++ )
g_last_buffer[ i ] = False;
}
void sing_buffer_volume_control( short *buffer_ptr, unsigned char level )
{
#define M_2_dB 52016
#define M_4_dB 41285
unsigned short i;
unsigned short shift;
unsigned short step;
long k;
#ifdef USE_AUDIO_PEAK_METER
unsigned long lev_l = 0;
unsigned long lev_r = 0;
#endif
if ( g_audio_mute )
{
for ( i = 0; i < MEMORY_FILLING_SIZE_FROM_FILE; i += 2 )
{
*buffer_ptr++ = 0;
*buffer_ptr++ = 0;
}
return;
}
shift = level / 3;
step = level % 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -