Linux_ALSA
小狼@http://blog.csdn.net/xiaolangyangyang
Control宏定义:
SOC_SINGLE_VALUE SOC_SINGLE_VALUE_EXT SOC_SINGLE SOC_SINGLE_TLV SOC_DOUBLE SOC_DOUBLE_R SOC_DOUBLE_TLV SOC_DOUBLE_R_TLV SOC_DOUBLE_S8_TLV SOC_ENUM_DOUBLE SOC_ENUM_SINGLE SOC_ENUM_SINGLE_EXT SOC_VALUE_ENUM_DOUBLE SOC_VALUE_ENUM_SINGLE SOC_ENUM SOC_VALUE_ENUM SOC_SINGLE_EXT SOC_DOUBLE_EXT SOC_SINGLE_EXT_TLV SOC_DOUBLE_EXT_TLV SOC_DOUBLE_R_EXT_TLV SOC_SINGLE_BOOL_EXT SOC_ENUM_EXT SOC_DOUBLE_R_SX_TLV SOC_ENUM_DOUBLE_DECL SOC_ENUM_SINGLE_DECL SOC_ENUM_SINGLE_EXT_DECL SOC_VALUE_ENUM_DOUBLE_DECL SOC_VALUE_ENUM_SINGLE_DECL
DAPM宏定义:
SND_SOC_DAPM_VMID SND_SOC_DAPM_INPUT SND_SOC_DAPM_OUTPUT SND_SOC_DAPM_MIC SND_SOC_DAPM_HP SND_SOC_DAPM_SPK SND_SOC_DAPM_LINE SND_SOC_DAPM_PGA SND_SOC_DAPM_OUT_DRV SND_SOC_DAPM_MIXER SND_SOC_DAPM_MIXER_NAMED_CTL SND_SOC_DAPM_MICBIAS SND_SOC_DAPM_SWITCH SND_SOC_DAPM_MUX SND_SOC_DAPM_VIRT_MUX SND_SOC_DAPM_VALUE_MUX SOC_PGA_ARRAY SOC_MIXER_ARRAY SOC_MIXER_NAMED_CTL_ARRAY SND_SOC_DAPM_PGA_E SND_SOC_DAPM_OUT_DRV_E SND_SOC_DAPM_MIXER_E SND_SOC_DAPM_MIXER_NAMED_CTL_E SND_SOC_DAPM_MICBIAS_E SND_SOC_DAPM_SWITCH_E SND_SOC_DAPM_MUX_E SND_SOC_DAPM_VIRT_MUX_E SND_SOC_DAPM_PGA_S SND_SOC_DAPM_SUPPLY_S SOC_PGA_E_ARRAY SOC_MIXER_E_ARRAY SOC_MIXER_NAMED_CTL_E_ARRAY SND_SOC_DAPM_PRE SND_SOC_DAPM_POST SND_SOC_DAPM_AIF_IN SND_SOC_DAPM_AIF_IN_E SND_SOC_DAPM_AIF_OUT SND_SOC_DAPM_AIF_OUT_E SND_SOC_DAPM_DAC SND_SOC_DAPM_DAC_E SND_SOC_DAPM_ADC SND_SOC_DAPM_ADC_E SND_SOC_DAPM_REG SND_SOC_DAPM_SUPPLY SOC_DAPM_SINGLE SOC_DAPM_SINGLE_TLV SOC_DAPM_ENUM SOC_DAPM_ENUM_VIRT SOC_DAPM_VALUE_ENUM SOC_DAPM_PIN_SWITCH
static const struct snd_kcontrol_new wmxx_mix1_controls[] = {
SOC_DAPM_SINGLE("SW1", WMXX_REG_SW, 1, 1, 0),
SOC_DAPM_SINGLE("SW2", WMXX_REG_SW, 2, 0, 0),
SOC_DAPM_SINGLE("SW3", WMXX_REG_SW, 3, 0, 0),
SOC_DAPM_SINGLE("SW4", WMXX_REG_SW, 4, 0, 0)
};
static const struct snd_kcontrol_new wmxx_mix2_controls[] = {
SOC_DAPM_SINGLE("SW5", WMXX_REG_SW, 5, 1, 0),
SOC_DAPM_SINGLE("SW6", WMXX_REG_SW, 6, 0, 0),
SOC_DAPM_SINGLE("SW7", WMXX_REG_SW, 7, 0, 0),
SOC_DAPM_SINGLE("SW8", WMXX_REG_SW, 8, 0, 0)
};
static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("MIX1", WMXX_REG_MIX, 1, 0, wmxx_mix1_controls, ARRAY_SIZE(wmxx_mix1_controls)),
SND_SOC_DAPM_MIXER("MIX2", WMXX_REG_MIX, 2, 0, wmxx_mix2_controls, ARRAY_SIZE(wmxx_mix2_controls))
};
static const struct snd_soc_dapm_route audio_map[] = {
{"MIX1", "SW2", "ADC"},
{"MIX2", "SW6", "MIX1"},
};
播放器代码
#include #include#include #include #include #define int8_t char #define int16_t short #define int32_t int #define int64_t long #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define uint64_t unsigned long typedef struct { uint32_t dwSize; uint16_t wFormatTag; uint16_t wChannels; uint32_t dwSamplesPerSec; uint32_t dwAvgBytesPerSec; uint16_t wBlockAlign; uint16_t wBitsPerSample; } WAVEFORMAT; typedef struct { uint8_t RiffID [4]; uint32_t RiffSize; uint8_t WaveID[4]; uint8_t FmtID[4]; uint32_t FmtSize; uint16_t wFormatTag; uint16_t nChannels; uint32_t nSamplesPerSec; uint32_t nAvgBytesPerSec; uint16_t nBlockAlign; uint16_t wBitsPerSample; uint8_t DataID[4]; uint32_t nDataBytes; } WAVE_HEADER; static int32_t set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, uint32_t ch, snd_pcm_format_t format, uint32_t rate, snd_pcm_sframes_t *period_size) { snd_pcm_uframes_t size; uint32_t rrate; int32_t err, dir; uint32_t buffer_time = 500000; uint32_t period_time = 100000; int32_t resample = 1; err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Broken configuration for playback: no configurations available: %sn", snd_strerror(err)); return err; } err = snd_pcm_hw_params_set_rate_resample(handle, params, resample); if (err < 0) { printf("Resampling setup failed for playback: %sn", snd_strerror(err)); return err; } err = snd_pcm_hw_params_set_access(handle, params, access); if (err < 0) { printf("Access type not available for playback: %sn", snd_strerror(err)); return err; } err = snd_pcm_hw_params_set_format(handle, params, format); if (err < 0) { printf("Sample format not available for playback: %sn", snd_strerror(err)); return err; } err = snd_pcm_hw_params_set_channels(handle, params, ch); if (err < 0) { printf("Channels count (%u) not available for playbacks: %sn", ch, snd_strerror(err)); return err; } rrate = rate; err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); if (err < 0) { printf("Rate %uHz not available for playback: %sn", rate, snd_strerror(err)); return err; } if (rrate != rate) { printf("Rate doesn't match (requested %uHz, get %iHz)n", rate, err); return -EINVAL; } err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir); if (err < 0) { printf("Unable to set buffer time %u for playback: %sn", buffer_time, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_buffer_size(params, &size); if (err < 0) { printf("Unable to get buffer size for playback: %sn", snd_strerror(err)); return err; } printf("buffer_size = %ldn", size); err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir); if (err < 0) { printf("Unable to set period time %u for playback: %sn", period_time, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_period_size(params, &size, &dir); if (err < 0) { printf("Unable to get period size for playback: %sn", snd_strerror(err)); return err; } *period_size = size; printf("period_size = %ldn", size); err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to set hw params for playback: %sn", snd_strerror(err)); return err; } return 0; } FILE * open_and_print_file_params(int8_t *file_name, WAVE_HEADER *g_wave_header) { FILE * fp = fopen(file_name, "r"); if (fp == NULL) { printf("can't open wav filen"); return NULL; } memset(g_wave_header, 0, sizeof(WAVE_HEADER)); fread(g_wave_header, 1, sizeof(WAVE_HEADER), fp); printf(">> RiffID : %c%c%c%cn", g_wave_header->RiffID[0], g_wave_header->RiffID[1], g_wave_header->RiffID[2], g_wave_header->RiffID[3]); printf(">> RiffSize : %dn", g_wave_header->RiffSize); printf(">> WaveID : %c%c%c%cn", g_wave_header->WaveID[0], g_wave_header->WaveID[1], g_wave_header->WaveID[2], g_wave_header->WaveID[3]); printf(">> FmtID : %c%c%c%cn", g_wave_header->FmtID[0], g_wave_header->FmtID[1], g_wave_header->FmtID[2], g_wave_header->FmtID[3]); printf(">> FmtSize : %dn", g_wave_header->FmtSize); printf(">> wFormatTag : %dn", g_wave_header->wFormatTag); printf(">> nChannels : %dn", g_wave_header->nChannels); printf(">> nSamplesPerSec : %dn", g_wave_header->nSamplesPerSec); printf(">> nAvgBytesPerSec : %dn", g_wave_header->nAvgBytesPerSec); printf(">> nBlockAlign : %dn", g_wave_header->nBlockAlign); printf(">> wBitsPerSample : %dn", g_wave_header->wBitsPerSample); printf(">> DataID : %c%c%c%cn", g_wave_header->DataID[0], g_wave_header->DataID[1], g_wave_header->DataID[2], g_wave_header->DataID[3]); printf(">> nDataBytes : %dn", g_wave_header->nDataBytes); return fp; } char * sctrlstr = "Digital Playback Volume"; int32_t main() { int8_t *infile = "Back_to_Earth.wav"; int8_t *device = "hw:0,0"; snd_pcm_t *handle; snd_pcm_hw_params_t *hwparams; WAVE_HEADER g_wave_header; snd_pcm_format_t format; uint32_t ch; uint32_t rate; snd_pcm_sframes_t period_size; int16_t *samples; int32_t music_sec; int32_t err; int32_t size; int32_t rc; FILE *fp = open_and_print_file_params(infile, &g_wave_header); if (fp == NULL) { printf("open_and_print_file_params errorn"); return -1; } rate = g_wave_header.nSamplesPerSec; if (8 == g_wave_header.FmtSize) { format = SND_PCM_FORMAT_U8; } else if (16 == g_wave_header.FmtSize) { format = SND_PCM_FORMAT_S16_LE; } else if (24 == g_wave_header.FmtSize) { format = SND_PCM_FORMAT_U24_LE; } else if (32 == g_wave_header.FmtSize) { format = SND_PCM_FORMAT_U32_LE; } else { printf("SND_PCM_FORMAT_UNKNOWN.n"); format = SND_PCM_FORMAT_UNKNOWN; return -1; } ch = g_wave_header.nChannels; music_sec = g_wave_header.nDataBytes / g_wave_header.nAvgBytesPerSec; printf("music_time : %d : %dn", (int32_t)music_sec / 60, music_sec % 60); printf("Playback device is %sn", device); printf("Stream parameters are %uHz, %s, %u channelsn", rate, snd_pcm_format_name(format), ch); err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { printf("Playback open error: %sn", snd_strerror(err)); return 0; } snd_pcm_hw_params_alloca(&hwparams); err = set_hwparams(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED, ch, format, rate, &period_size); if (err < 0) { printf("Setting of hwparams failed: %sn", snd_strerror(err)); return 0; } size = (period_size * ch * snd_pcm_format_physical_width(format)) / 8; samples = (int16_t *)malloc(size); while (1) { rc = fread(samples, sizeof(int16_t), size, fp); if (rc == 0) { printf("end of file on inputn"); break; } else if (rc != size) { printf("short read: read %d bytesn", rc); } rc = snd_pcm_writei(handle, samples, size); if (rc == -EPIPE) { printf("underrun occurredn"); err = snd_pcm_prepare(handle); if( err < 0) { printf("can not recover from underrun: %sn", snd_strerror(err)); } } else if (rc < 0) { printf("error from writei: %sn", snd_strerror(rc)); } else if (rc != (int32_t)size) { printf("short write, write %d framesn", rc); } } if (samples != NULL) { free(samples); } snd_pcm_close(handle); return 0; }
# arm-fsl-linux-gnueabi-gcc player.c -o player -lasound -lm -I /var/alsa/include/ -L /var/alsa/lib/
Linux/Android alsa codec音频路由dapm的配置详解
DAPM之二:audio paths与dapm kcontrol
ALSA声卡16_编写ALSA声卡应用程序_学习笔记
8.声卡驱动06-自己实现alsa驱动-虚拟声卡-widget
ALSA驱动asoc框架之machine(一)
ALSA驱动asoc框架之machine(二)
ALSA驱动asoc框架之Platform
ALSA驱动asoc框架之Codec
Linux ALSA 音频系统:物理链路篇
Linux ALSA 音频系统:逻辑设备篇



