混音器原理及Mixer API函数介绍3

Android音频驱动-ASOC之Control Open struct mixer *mixer_open(unsigned int card) { struct snd_ctl_elem_list elist; struct snd_ctl_elem_info tmp; struct snd_ctl_elem_id *eid = NULL; struct mixer *mixer = NULL; unsigned 阅读详情

获取、设置某个控件的值

现在,我们讲述混音器的目标——获取一个控件的值(这样你就可以将其当前的值显示给终端用户),和设置一个控件的值(这样可以让终端用户调整控件的值)。

想要获取或设置某个控件的值,你必须知道此控件的ID。可以通过mixerGetControlDetails()获取其当前值,通过mixerSetControlDetails()设置为某个特定的值。这些函数都使用一个类型为MIXERCONTROLDETAILS的结构体。你可以初始化其中的部分域来告诉

mixerGetControlDetails()/mixerSetControlDetails()你想设置/获取哪个控件的值。你同时还得提供另外一个即将存放值的结构。

例如,我们获取线路Speaker Out的音量滑动器控件的当前值,到目前位置,我们已知道了怎样获取这个控件的信息(例如,这个控件的ID)。为了获取控件的值,我们需要提供一个特殊的结构体来存放返回值。

我们需要使用什么样的结构?哦,这要看控件的类型了。音量滑动器控件的类型为

MIXERCONTROL_CONTROLTYPE_VOLUME,如果你回头看一下chart about the fader class of controls,就知道了这个值将使用一个类型为MIXERCONTROLDETAILS_UNSIGNED的结构。这个结构只有一个域dwValue,用于存放返回值。因此我们提供一个MIXERCONTROLDETAILS_UNSIGNED类型的结构给mixerGetControlDetails()(通过MIXERCONTROLDETAILS结构),如下是一个样例程序,获取并输出Speaker Out线路中音量滑动器控件的当前值。

/* We need a MIXERCONTROLDETAILS_UNSIGNED struct to retrieve the     value of a control whose type is MIXERCONTROL_CONTROLTYPE_VOLUME */  
MIXERCONTROLDETAILS_UNSIGNED value;  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    
/* Tell mixerGetControlDetails() which control whose value we     want to retrieve. We do this by putting the desired control's     ID number in dwControlID. Remember that the "Speaker Out" line's     volume slider has an ID of 0x00000000 */  mixerControlDetails.dwControlID = 0x00000000;    
/* This is always 1 for a MIXERCONTROL_CONTROLF_UNIFORM control */  mixerControlDetails.cChannels = 1;    
/* This is always 0 except for a MIXERCONTROL_CONTROLF_MULTIPLE control */  mixerControlDetails.cMultipleItems = 0;    
/* Give mixerGetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED struct into which to return the value */  
mixerControlDetails.paDetails = &value;    
/* Tell mixerGetControlDetails() how big the MIXERCONTROLDETAILS_UNSIGNED is */  mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    
/* Retrieve the current value of the volume slider control for this line */  
if ((err = mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE)))  
{      /* An error */      
printf("Error #%d calling mixerGetControlDetails()\n", err);  }  
else  
{      printf("It's value is %lu\n", value.dwValue);  }  

若要设置一个控件的值,你只需填充此结构,然后将其传递给mixerSetControlDetails()。你同时还要指定MIXER_SETCONTROLDETAILSF_VALUE结构。这里是一个样例程序,其将线路 Speaker Out的音量滑动器控件的值设置为31。

 

MIXERCONTROLDETAILS_UNSIGNED value;  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    
/* Tell mixerSetControlDetails() which control whose value we     want to set. We do this by putting the desired control's     ID number in dwControlID. Remember that the "Speaker Out" line's     volume slider has an ID of 0x00000000 */  
mixerControlDetails.dwControlID = 0x00000000;   
/* This is always 1 for a MIXERCONTROL_CONTROLF_UNIFORM control */  mixerControlDetails.cChannels = 1;    
/* This is always 0 except for a MIXERCONTROL_CONTROLF_MULTIPLE control */  mixerControlDetails.cMultipleItems = 0;    
/* Give mixerSetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED struct into which we place the value */  
mixerControlDetails.paDetails = &value;    
/* Tell mixerSetControlDetails() how big the MIXERCONTROLDETAILS_UNSIGNED is */  mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    
/* Store the value */  
value.dwValue = 31;    
/* Set the value of the volume slider control for this line */  
if ((err = mixerSetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE)))  
{      /* An error */      
printf("Error #%d calling mixerSetControlDetails()\n", err);  
}  

多声道控件

前面已说过,当将设置了控件的MIXERCONTROL_CONTROLF_UNIFORM标志时,所有声道都共享同一个值。例如,对于Speaker Out线路,它是立体声线路,但是其左右声道并没有独立的值。

但是,若一个控件的MIXERCONTROL_CONTROLF_UNIFORM值没有设置,并且此控件有一个以上的声道,那么每个声道都有一个独立的值。因为这个原因,当你设置/获取某个控件的值时,你必须提供多个特殊的结构。例如,假设Speaker Out线路的音量滑动器控件没有设置

MIXERCONTROL_CONTROLF_UNIFORM标志。因为此线路有两个声道,所以我们必须提供两个MIXERCONTROLDETAILS_UNSIGNED结构来存放获取/设置其左右声道的值,

我们需要使用一个类型为MIXERCONTROLDETAILS_UNSIGNED的数组。第一个MIXERCONTROLDETAILS_UNSIGNED结构将存放第一个声道的值,第二个结构将存放第二个声道的值。如下是一个样例程序,获取我们的Speaker Out线路的音量滑动器控件的左右声道的值:

/* We need 2 MIXERCONTROLDETAILS_UNSIGNED structs to retrieve the     values of a stereo control that is not MIXERCONTROL_CONTROLF_UNIFORM */  
MIXERCONTROLDETAILS_UNSIGNED value[2];  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    
/* Tell mixerGetControlDetails() which control whose value we     want to retrieve. We do this by putting the desired control's     ID number in dwControlID. Remember that the "Speaker Out" line's     volume slider has an ID of 0x00000000 */  mixerControlDetails.dwControlID = 0x00000000;    
/* We want to retrieve values for both channels */  
mixerControlDetails.cChannels = 2;    
/* This is always 0 except for a MIXERCONTROL_CONTROLF_MULTIPLE control */  mixerControlDetails.cMultipleItems = 0;    
/* Give mixerGetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED array into which to return the values */  
mixerControlDetails.paDetails = &value[0];    /* Tell mixerGetControlDetails() how big each MIXERCONTROLDETAILS_UNSIGNED is */  
mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    
/* Retrieve the current values of both channels */  
if ((err = mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE)))  
{      /* An error */      
	printf("Error #%d calling mixerGetControlDetails()\n", err);  }  
else  
{	printf("The left channel's volume is %lu\n", value[0].dwValue);      
	printf("The right channel's volume is %lu\n", value[1].dwValue);  
}  

To set the values of both channels, you fill in the values of both MIXERCONTROLDETAILS_UNSIGNED structs. Here is an example of setting the left channel's volume to 31 and the right channel's volume to 0.

/* We need 2 MIXERCONTROLDETAILS_UNSIGNED structs to set the     values of a stereo control that is not MIXERCONTROL_CONTROLF_UNIFORM */  
MIXERCONTROLDETAILS_UNSIGNED value[2];  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    
/* Tell mixerSetControlDetails() which control whose value we     want to set. We do this by putting the desired control's     ID number in dwControlID. Remember that the "Speaker Out" line's     volume slider has an ID of 0x00000000 */  
mixerControlDetails.dwControlID = 0x00000000;    
/* We want to set values for both channels */  
mixerControlDetails.cChannels = 2;    
/* This is always 0 except for a MIXERCONTROL_CONTROLF_MULTIPLE control */  mixerControlDetails.cMultipleItems = 0;    
/* Give mixerSetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED structs into which we place the values */  
mixerControlDetails.paDetails = &value[0];    
/* Tell mixerSetControlDetails() how big each MIXERCONTROLDETAILS_UNSIGNED is */  mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    
/* Store the left channel's value */  
value[0].dwValue = 31;    
/* Store the right channel's value */  
value[1].dwValue = 0;    
/* Set the left/right values of the volume slider control for this line */  
if ((err = mixerSetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE)))  
{      
	/* An error */      
	printf("Error #%d calling mixerSetControlDetails()\n", err);  
}
 

当然,一个控件或许有2个以上的控件。对一个给定的控件,你必须提供足够大的结构来容纳所有的声道的值。因此,你必须根据需要来开辟数组空间。

一次存取一个控件中的某几个声道是非法的。例如,一个控件有8个声道,但是你只取其前2个声道的值,这是不允许的。你必须同时存取一个控件的所有声道才可以。但是这里有一条有关设置一个值的规则:如果你仅仅设置第一个声道的值,那么

mixerSetControlDetails()自动将控件设置MIXERCONTROL_CONTROLF_UNIFORM标志。最终结果是此控件的所有声道都被设置为这个值。因此,你可以通过仅仅设置第一个声道的值来达到将所有的声道设置为同一个值的目的。

多条目控件

你不会经常碰到“多条目”控件。一个多条目控件就是那种一个声道关联着多个值的控件。

下面是一个图形均衡器控件。让我们简单的学习一下这个样例。假设一个声卡中有以下3个图形均衡器。

                                   

混音器原理及Mixer API函数介绍3 - 我,猪八戒 - 我,猪八戒的博客

这个控件有3个值与其关联—与“低通道”关联的值、与“中通道”关联的值、与“高通道”关联的值。(注:假设每个通道都能设置为不同的值,否则它就是一个无用的图形均衡器了)。这样表现出来的就是一个多条目控件,它有3个值与其关联。

我们再进一步假设这个控件属于Speaker Out线路。

我们来看一下MIXERCONTROL结构体。一个多条目控件的MIXERCONTROL的域dwControlType值会有MIXERCONTROL_CONTROLF_MULTIPLE位标志设置。MIXERCONTROL  的cMultipleItems域同时会告诉你每个声道有几个条目。

MIXERCONTROL mixerctl_EQ = {      
sizeof(MIXERCONTROL),            /* size of a MIXERCONTROL */      0x00000002,                      /* unique ID # for this control */      MIXERCONTROL_CONTROLTYPE_EQUALIZER, /* type of control */      MIXERCONTROL_CONTROLF_UNIFORM|MIXERCONTROL_CONTROLF_MULTIPLE,   /* flag bits */      3,                               /* # of items perchannel*/      
"EQ",                            /* Short name for this control */      
"Graphic Equalizer",             /* Long name for this control */      0,                               /* Minimum value to which this control can be set */      65535,                           /* Maximum value to which this control can be set */      0, 0, 0, 0,                      /* These fields are reserved for future use */      31,                              /* Step amount for the value */      
0, 0, 0, 0, 0,                   /* These fields are reserved for future use */  
};  

首先,注意控件ID不同于此混音器中其它控件的ID。同样要注意的是,还设置了MIXERCONTROL_CONTROLF_MULTIPLE位标志。cMultipleItems被设置为3,表明每个声道有3个条目。(但是我已将此控件设置了MIXERCONTROL_CONTROLF_UNIFORM标志,因此总共只有3个值,即使线路Speaker Out是立体声的。换句话说,每个通道的值同时影响着所有声道)

为了获取3个通道的值,我们需要一个包含3个结构的数组。需要什么类型的结构呢?哦,类型为MIXERCONTROL_CONTROLTYPE_EQUALIZER的控件的种类是fader,因此你会想起此种类的值都使用MIXERCONTROLDETAILS_UNSIGNED类型的结构。如下展示了怎样获取3个通道的值。

/* We need 3 MIXERCONTROLDETAILS_UNSIGNED structs to retrieve the     values of this control */  
MIXERCONTROLDETAILS_UNSIGNED value[3];  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    
/* Tell mixerGetControlDetails() which control whose value we     want to retrieve */  mixerControlDetails.dwControlID = 0x00000002;    
/* It's a MIXERCONTROL_CONTROLF_UNIFORM control, so the values     for all channels are the same as the first */  
mixerControlDetails.cChannels = 1;    /* There are 3 items per channel */  mixerControlDetails.cMultipleItems = 3;    /* Give mixerGetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED array into which to return the values */  mixerControlDetails.paDetails = &value[0];    
/* Tell mixerGetControlDetails() how big each MIXERCONTROLDETAILS_UNSIGNED is */  
mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    
/* Retrieve the current values of all 3 bands */  
if ((err = mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE)))  
{      
/* An error */      
	printf("Error #%d calling mixerGetControlDetails()\n", err);  
}  
else  
{     printf("The Low band is %lu\n", value[0].dwValue);      
	printf("The Mid band is %lu\n", value[1].dwValue);      
	printf("The High band is %lu\n", value[2].dwValue);  
}  

To set the values of all 3 bands, you fill in the values of the MIXERCONTROLDETAILS_UNSIGNED structs. Here is an example of setting the Low band to 31, the Mid band to 0, and the High band to 62.

/* We need 3 MIXERCONTROLDETAILS_UNSIGNED structs to set the     values of the 3 bands */  MIXERCONTROLDETAILS_UNSIGNED value[3];  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    
/* Tell mixerSetControlDetails() which control whose values we     want to set */  mixerControlDetails.dwControlID = 0x00000002;    
/* The values for all channels are the same as the first channel */  mixerControlDetails.cChannels = 1;    /* We're setting all 3 bands */  mixerControlDetails.cMultipleItems = 3;    /* Give mixerSetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED structs into which we place the values */  mixerControlDetails.paDetails = &value[0];    /* Tell mixerSetControlDetails() how big each MIXERCONTROLDETAILS_UNSIGNED is */  
mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    /* Store the Low band's value */  
value[0].dwValue = 31;    /* Store the Mid band's value */  value[1].dwValue = 0;    /* Store the High band's value */  
value[2].dwValue = 62;    /* Set the values of the 3 bands for this control */  
if ((err = mixerSetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE)))  
{      /* An error */      
	printf("Error #%d calling mixerSetControlDetails()\n", err);  
}  

现在我们将控件的MIXERCONTROL_CONTROLF_UNIFORM标志去掉。因此,每个声道的每个条目都有其自己的值。因为Speaker Out 有两个声道,那意味着我们需要总计为2 (声道) * 3 (条目)个结构,也就是6个值。我们的图形均衡器如下图所示:  

 

混音器原理及Mixer API函数介绍3 - 我,猪八戒 - 我,猪八戒的博客混音器原理及Mixer API函数介绍3 - 我,猪八戒 - 我,猪八戒的博客
Left ChannelRight Channel

我们需要6个类型为MIXERCONTROLDETAILS_UNSIGNED的结构来存放所有声道的所有条目的值。哦,在前面的样例程序中,我都将这些条目的标签设置过了。如果你希望将他们输出,你就应该向混音器询问这些值。为了达到这个目标,你必须提供一个类型为MIXERCONTROLDETAILS_LISTTEXT结构的数组,就像你提供一组类型为MIXERCONTROLDETAILS_UNSIGNED的结构来获取所有声道的所有条目的值一样。

/* We need 6 MIXERCONTROLDETAILS_UNSIGNED structs to retrieve the     values of this control */  
MIXERCONTROLDETAILS_UNSIGNED value[6];  /* We need 6 MIXERCONTROLDETAILS_LISTTEXT structs to retrieve the     labels of all items */  
MIXERCONTROLDETAILS_LISTTEXT label[6];  
MIXERCONTROLDETAILS          mixerControlDetails;  
MMSYSTEM                     err;    
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);    /* Tell mixerGetControlDetails() which control whose value we     want to retrieve */  mixerControlDetails.dwControlID = 0x00000002;    /* Our "Speaker Out" has 2 channels */  mixerControlDetails.cChannels = 2;    /* There are 3 items per channel */  mixerControlDetails.cMultipleItems = 3;    /* Give mixerGetControlDetails() the address of the     MIXERCONTROLDETAILS_UNSIGNED array into which to return the values */  mixerControlDetails.paDetails = &value[0];    /* Tell mixerGetControlDetails() how big each MIXERCONTROLDETAILS_UNSIGNED is */  
mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);    /* Retrieve the current values of all 3 bands for both channels */  
if ((err = mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE)))  
{      
/* An error */      
	printf("Error #%d calling mixerGetControlDetails()\n", err);  
}  
else  
{      unsigned long   i,n;        /* Let's fetch the labels of all the items */        		mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);      	mixerControlDetails.dwControlID = 0x00000002;      
	mixerControlDetails.cChannels = 2;      
	mixerControlDetails.cMultipleItems = 3;        /* Give mixerGetControlDetails() the address of the         MIXERCONTROLDETAILS_LISTTEXT array into which to return the labels */      
	mixerControlDetails.paDetails = &label[0];        /* Tell mixerGetControlDetails() how big each MIXERCONTROLDETAILS_LISTTEXT is */      
	mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT);        /* Retrieve the labels of all items for both channels, Note         that I specify MIXER_GETCONTROLDETAILSF_LISTTEXT */      
	if ((err = mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_LISTTEXT)))      
	{          /* An error */          
		printf("Error #%d calling mixerGetControlDetails()\n", err);      
	}      
	else      
	{          /* Print the values of all items */          
		for (i = 0; i < 2; i++)          
		{              
			printf("Channel %lu:\n", i+1);                
			for (n = 0; n < 3; n++)              
			{      
				printf("\tThe %s item is %lu\n", label[3 * i + n].szName, value[3 * i + n].dwValue);      
			}          
		}      
	}  
}  

一次获取或设置控件中几个条目的值是不行的。例如,若一个控件有8个条目,你仅仅获取其前2个条目的控件是不允许的。你必须同时设置/获取所有的声道的所有条目的值。关于设置条目的值,这里有一个规则:如果你仅仅设置第一个声道的条目的值,那么mixerSetControlDetails()会自动将控件设置MIXERCONTROL_CONTROLF_UNIFORM标记。最终结果就是所有声道的所条目的值都和第一个声道的条目的值相同。因此,你可以通过只设置第一个声道的条目的值达到将所有的声道的条目的值设为相同值的目的。

改变通知

在上面的样例程序中,我已展示了通过mixerOpen()函数打开混音器然后将其返回值用作其它函数。不一定非得这样做。实际上,Mixer API被设计为可以按以下方式使用:取代将打开的混音器句柄作为混音器函数的某个参数的一种方式是,你可以传递混音器ID。因此,你不必显式的打开混音器。

但是如果你想做某些操作,显式的打开混音器设备(通过mixerOpen()函数)会有一些优点。

首先,这会防止混音器被卸载(大概是声卡的驱动所为)。其次,在你打开了一个混音器后,当此混音器的任何线路的状态发生改变时(比如线路被设置为静音),或者某个控件的值改变时,你可以命令windows系统发送一个消息(到你自定义的窗口程序)通知你。你不仅仅在你改变某个线路的状态或某个控件的值时获得这些消息,而且当其它程序打开混音器(注:多个程序可以同时打开一个混音器)并改变某个线路的状态或某个控件的值时也能获取这些消息。因此,当其它程序对混音器做改变时,你可以使你的程序与混音器的状态保持同步。

当你调用mixerOpen()时,你应该将接受通知消息的窗口句柄作为地上那个参数传递给此函数,并将CALLBACK_WINDOW传递给最后一个参数。

这里有2个特殊的“混音器消息”。

MM_MIXM_LINE_CHANGE:当混音器的任何一个线路的状态发生改变时,系统会发送此消息到你的窗口处理程序。

    MM_MIXM_CONTROL_CHANGE:当混音器中的任何一个控件的值发生改变时,系统会发送此消息到你的窗口处理程序。

    对于MM_MIXM_LINE_CHANGE,WPARAM参数表示发生改变的线路所属的混音器句柄,LPARAM参数表示此线路的ID。

    对于MM_MIXM_CONTROL_CHANGE,WPARAM参数表示发生改变的线路所属的混音器句柄,LPARAM参数表示值发生改变的控件的ID。

总结

Mixer API是windows多媒体中最复杂的一组API。你需要一点时间来读懂这篇教程然后将它应用于你的程序中。但是Mixer API使得你可以操作任何已安装的声卡,而不必对某个特定的声卡编写特定的程序。

想获取更多关于混音器结构和API的信息,请参考Microsoft Developer Network's reference upon audio mixers 。

微软提供了一个免费下载的关于使用Mixer API的样例程序。但是我发现此代码的注释太简单了,同时有很多和Mixer API无关并且是不必要的代码。我已将此样例程序精简,使得其都是展示如何使用Mixer API的关键代码,并添加了很多注释。你可以下载我修改的版本Microsoft's Mixer Device Example,它将展示了如何显示所有的混音器设备和它们的线路/控件,以及调整控件的值。这个工程是基于Visual C++4.0的,因为它是一个普通的用C语言编写的windows应用程序,因此任何windows的C语言编译器应该都可以编译它。

Tinyalsa之mixer_ctl_set_value(十) static int set_route_by_array_v2(struct mixer *mixer, struct route_setting *route) { struct mixer_ctl *ctl; . 阅读详情

相关推荐

Qualcomm(高通)平台开发系列讲解-音频设备操作流程

本篇将介绍高通平台音频的操作基于高通平台,高通提供了libalsa-inf库来操作音频设备,下面介绍设置音频设备及操作步骤.

Poorest的博客 2152

android Audio 详解( 二 )

2  tinyalsa    tinyalsa是Google在Android 4.0之后推的基于alsa内核的用户层音频接口。在Android 4.0之前还一直是使用这alsa-lib接口。Google之所以推出tinyalsa,可能是因为alsa使用了GPL许可证的缘故,也有可能是因为alsa-lib的库过于复杂繁琐而大部分功能在Android平台没有实际实用意义却依然占用屈指可数的内

wince_lover的专栏 5337

ADS2020实战:手把手教你搭建交叉耦合VCO并分析相位噪声(附避坑指南)

本文以ADS2020软件为例,提供了交叉耦合压控振荡器(VCO)从原理图搭建到相位噪声分析的完整实战指南。详细讲解了核心器件选择、谐波平衡与瞬态仿真的关键设置,并重点剖析了相位噪声的仿真方法与优化方向。文中附有详细的避坑指南,帮助初学者和工程师高效完成VCO设计与仿真验证,避免常见错误。

p5l2m9n4o6q的博客 277

Audio:Android-TinyAlsa架构 Mixer API

Android中对音频多声道数据的配置binary tinymix是tinyplay执行前必要的步骤,对tinymix的源码进行check在整合tinyalsa相关通道配置以及流程上是非常有必要的。tinymix梳理之后还是比较简单的,主要有mixer_open, mixer_close,tinymix_list_controls, tinymix_detail_control,tinymix_set_value这个几个方法。 1.tinymix.c file path: exter...

Cmatrix204的博客 5924

多智能体强化学习之值函数分解:VDN、QMIX、QTRAN系列优缺点分析(转载)

关于多智能体强化学习中VDN,QMIX,QTRAN三个算法再值分解方向的研究成果。三个算法呈递进关系

qq_33328642的博客 5859

VM与欧姆龙PLC通讯设置:Fins TCP/UDP协议实战避坑指南

本文详细解析了VM视觉平台与欧姆龙PLC通过Fins TCP/UDP协议进行通讯的实战配置与避坑要点。文章对比了Fins TCP与Fins UDP的差异,推荐在多数工业控制场景下优先选用Fins TCP以保证可靠性,并深入讲解了网络设置、寄存器地址映射、轮询优化等核心配置步骤。同时,针对常见的多次触发拍照、数据解析错误等问题提供了具体的解决方案和调试技巧,旨在帮助工程师快速建立稳定高效的通讯连接。

e4f5g6h7的博客 596

混音器原理及Mixer API函数介绍

混音器原理及Mixer API函数介绍 为了理解Mixer API是如何工作的,首先我们得弄清楚一个典型声卡的硬件组成。因此非常有必要去建立一个声卡模型,此声卡应拥有多个典型的组件并且这些组件都是相关联的。让我们看一个典型的、最基本的声卡。首先,如果声卡能够进行数字化录音,那么典型情况下它就有一个Microphone Input(麦克风传声器,下同)(附有某种前置放大器),同时它还有一

没有时间把一件事情做好,却有时间把一件事情反复做 1万+

matlab实现MSK调制解调

文章目录一、要求二、设计三、代码四、结果五、结论 一、要求 画出MSK信号产生的信息、I路、Q路信号对比图以及接收端解调的信息恢复的对比图。 二、设计 1.MSK调制 2.MSK解调 三、代码 clear all;clc; N=20; T=1; fc=10; Fs=100; bitstream=randi([0,1],1,N); bitstream1=2*bitstream-1; b0=1; for i=1:N encode_output(i)=b0*bitstream

Time_book的博客 1万+

混音器原理及Mixer API函数介绍1

为了理解Mixer API是如何工作的,首先我们得弄清楚一个典型声卡的硬件组成。因此非常有必要去建立一个声卡模型,此声卡应拥有多个典型的组件并且这些组件都是相关联的。 让我们看一个典型的、最基本的声卡。首先,如果声卡能够进行数字化录音,那么典型情况下它就有一个Microphone Input(麦克风传声器,下同)(附有某种前置放大器),同时它还有一个ADC(模数转换器,下同)将麦克风输入的模

LearnITing的专栏 2935

微生物组β-多样性——PCoA分析及可视化

让你的数据映入眼帘

qq_47369980的博客 1万+

CANoe数据回放实战:如何用Replay Block精准复现实车故障(附ECU数据处理技巧)

本文深入探讨了利用CANoe的Replay Block功能进行数据回放,以精准复现实车偶发性故障的实战方法。文章重点解析了从原始OBD日志中移除目标ECU数据、转换报文方向等核心数据处理技巧,旨在帮助工程师重构真实的网络测试环境,从而高效定位并解决复杂的ECU问题。

nnn11的博客 496

混音器编程接口讨论

转自:http://www.cnblogs.com/windviki/archive/2011/08/31/2160683.html 混音器编程接口讨论 翻译:windviki@gmail.com 转载请注明 译自:MIXER API ARGUMENTATION 为了理解混音器API是如何工作的,必须先了解典型的声卡的硬件布局。 我们有必要想象一下,声卡上有各种独

yi7900的专栏 3536

vivado2020.2安装教程:Windows平台完整指南

手把手带你完成vivado2020.2安装教程,覆盖下载、配置到验证全过程,解决常见安装问题,确保在Windows平台顺利部署开发环境,适合初学者快速上手。

weixin_42607969的博客 1345

android音频低延时设计:Fast Mixer官方文档

本文介绍了Android系统中降低音频延迟的两种技术方案:FAST Mixer和AAudio MMAP。FAST Mixer通过创建高优先级的快速混音器线程,以2-5ms周期处理少量音轨,实现低延迟音频输出;AAudio MMAP则为原生应用提供更低延迟的音频通道。文章详细阐述了音轨创建机制、混音器线程架构(包括快速混音器和常规混音器的功能差异、调度策略及交互关系),并指出该设计主要面向设备厂商而非应用开发者,需要结合具体硬件特性进行实现。

liaosongmao1的专栏 37

生成式引擎优化(GEO)全景指南:技术架构、实施策略与未来趋势

生成式引擎优化(GEO)全景指南摘要 GEO(生成式引擎优化)是针对AI生成内容(如ChatGPT、文心一言等)的优化策略,通过结构化数据、权威建设与语义优化提升企业内容在AI答案中的引用优先级,实现“无点击曝光”。其核心价值在于从流量竞争转向信任构建,突破传统SEO局限。技术架构依托RAG(检索增强生成)、向量数据库及反馈学习机制,动态优化内容生成与引用逻辑。实施策略包括:部署结构化数据(如JSON-LD)、维护动态知识图谱、适配多模态内容(3D/VR)、联合权威机构发布白皮书。行业案例显示,美妆、智能家

解锁AI流量新红利!🚀 GEO优化(生成引擎优化)助您掌控AI搜索,让AI成为您的品牌最佳代言人! 1451

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

上一篇: 混音器原理及Mixer API函数介绍2
下一篇: 给想用技术改变时间的年轻人的建议
LearnITing
博客等级 码龄15年 14粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值