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

📄 sing.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	{
		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 + -