android soundrecorder之三 录音流程及数据流向

前两篇文章分别介绍了linux alsa结构和android soundrecorder的应用层实现

除了板级的初始过程,其他都是关于类层次关系的一些静态说明

这章主要介绍下录音的动态过程,以及数据是如何一步步获取和保存的

还是先上图:


这个图大致介绍了soundrecord的流程,alsa到kernel部分还有个control模块这里没有画出来

下面一张图里面会提到,实际上control模块还是影响我们代码量主要的模块,主要就是mixer和muxer的配置

HAL层以上前面已经说过了,这里我们关注HAL以下部分:

  1. 应用层点击录音按钮
  2. tinyalsa打开设备文件节点/dev/snd/pcmC0D0c,给出相应的采样通道,采样率,一帧数据大小,总buffer大小等
  3. tinyalsa打开设备文件节点/dev/snd/controlC0,设置codec内部相关寄存器,选择输入输出device,配置内部route,即所谓dapm
  4. tinyalsa通过pcmC0D0c触发录音开始,dai_link上时钟开启,dapm建立后,从main_mic接收的pcm信号就会通过codec内部route发送到AIFADCDAT线上cpu exynos4412这边AIFDACDAT接收pcm信号数据后,通过移位器将数据保存到I2S的RX_FIFO
  5. RX_FIFO收到数据,触发DMA控制器开始拷贝数据,DMA(pl330)将RX_FIFO中的数据拷贝到DMA专有的内存缓冲,本例中snd_dma_buffer起始物理地址addr=0x6036_0000
  6. tinyalsa通过ioctl向设备节点/dev/snd/pcmC0D0c发起读数据请求,snd_pcm会将dma缓冲buffer中的数据拷贝到tinyalsa传入的用户buffer中

下面这张顺序图详细记录了soundrecorder开启录音之后alsa的交互流程:

 

这里我要提到的是在snd_pcm_open之后,有很大一段代码是做constraint检查

最开始我在调试的时候这个constraint检查一直不过,也就是上面的1.1节点,然后后面的过程没法进行下去

snd_pcm_open()时增加了一大推rule;这些rule的作用其实就是检查tinyalsa指定的config对于当前dai_link是否支持

  1. int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)  
  2. {  
  3.     struct snd_pcm_runtime *runtime = substream->runtime;  
  4.     struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;  
  5.     int k, err;  
  6.   
  7.     for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {  
  8.         snd_mask_any(constrs_mask(constrs, k));  
  9.     }  
  10.   
  11.     for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {  
  12.         snd_interval_any(constrs_interval(constrs, k));  
  13.     }  
  14.   
  15.     snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS));  
  16.     snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE));  
  17.     snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES));  
  18.     snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS));  
  19.     snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS));  
  20.   
  21.     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,  
  22.                    snd_pcm_hw_rule_format, NULL,  
  23.                    SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);  
  24.     if (err < 0)  
  25.         return err;  
  26.     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,   
  27.                   snd_pcm_hw_rule_sample_bits, NULL,  
  28.                   SNDRV_PCM_HW_PARAM_FORMAT,   
  29.                   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);  
  30.     if (err < 0)  
  31.         return err;  
  32.     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,   
  33.                   snd_pcm_hw_rule_div, NULL,  
  34.                   SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);  
  35.     if (err < 0)  
  36.         return err;  
  37.     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,   
  38.                   snd_pcm_hw_rule_mul, NULL,  
  39.                   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);  
  40. .......  
  41. }  

其过程是这样的:

首先snd_pcm_hardware会声明自己支持的通道数,格式等,buffer_bytes_max是buffer总大小,其他值我也没有详细研究

基本按照linux原生拷贝,没有修改

  1. static const struct snd_pcm_hardware dma_hardware = {  
  2.     .info           = SNDRV_PCM_INFO_INTERLEAVED |  
  3.                     SNDRV_PCM_INFO_BLOCK_TRANSFER |  
  4.                     SNDRV_PCM_INFO_MMAP |  
  5.                     SNDRV_PCM_INFO_MMAP_VALID |  
  6.                     SNDRV_PCM_INFO_PAUSE |  
  7.                     SNDRV_PCM_INFO_RESUME,  
  8.     .formats        = SNDRV_PCM_FMTBIT_S16_LE |  
  9.                     SNDRV_PCM_FMTBIT_U16_LE |  
  10.                     SNDRV_PCM_FMTBIT_U8 |  
  11.                     SNDRV_PCM_FMTBIT_S8,  
  12.     .channels_min       = 1,  
  13.     .channels_max       = 2,  
  14.     .buffer_bytes_max   = 128*1024,  
  15.     .period_bytes_min   = PAGE_SIZE,  
  16.     .period_bytes_max   = PAGE_SIZE*2,  
  17.     .periods_min        = 2,  
  18.     .periods_max        = 128,  
  19.     .fifo_size      = 32,  
  20. };  

codec_dai这边声明如下:

  1. static struct snd_soc_dai_driver wm8994_dai[] = {  
  2.     {  
  3.         .name = "wm8994-aif1",  
  4.         .id = 1,  
  5.         .playback = {  
  6.             .stream_name = "AIF1 Playback",  
  7.             .channels_min = 1,  
  8.             .channels_max = 2,  
  9.             .rates = WM8994_RATES,  
  10.             .formats = WM8994_FORMATS,  
  11.         },  
  12.         .capture = {  
  13.             .stream_name = "AIF1 Capture",  
  14.             .channels_min = 1,  
  15.             .channels_max = 2,  
  16.             .rates = WM8994_RATES,  
  17.             .formats = WM8994_FORMATS,  
  18.          },  
  19.         .ops = &wm8994_aif1_dai_ops,  
  20.     },  
  21.     };  

cpu_dai这边声明如下:

  1. struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)  
  2. {  
  3.     struct i2s_dai *i2s;  
  4.     i2s = kzalloc(sizeof(struct i2s_dai), GFP_KERNEL);  
  5.     i2s->pdev = pdev;  
  6.     i2s->pri_dai = NULL;  
  7.     i2s->sec_dai = NULL;  
  8.     i2s->i2s_dai_drv.symmetric_rates = 1;  
  9.     i2s->i2s_dai_drv.probe = samsung_i2s_dai_probe;  
  10.     i2s->i2s_dai_drv.remove = samsung_i2s_dai_remove;  
  11.     i2s->i2s_dai_drv.ops = &samsung_i2s_dai_ops;  
  12.     i2s->i2s_dai_drv.suspend = i2s_suspend;  
  13.     i2s->i2s_dai_drv.resume = i2s_resume;  
  14.     i2s->i2s_dai_drv.playback.channels_min = 2;  
  15.     i2s->i2s_dai_drv.playback.channels_max = 2;  
  16.     i2s->i2s_dai_drv.playback.rates = SAMSUNG_I2S_RATES;  
  17.     i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;  
  18.     if (!sec) {  
  19.         i2s->i2s_dai_drv.capture.channels_min = 1;  
  20.         i2s->i2s_dai_drv.capture.channels_max = 2;  
  21.         i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;  
  22.         i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;  
  23.     } else {    /* Create a new platform_device for Secondary */  
  24.         i2s->pdev = platform_device_register_resndata(NULL,  
  25.                 pdev->name, pdev->id + SAMSUNG_I2S_SECOFF,  
  26.                 NULL, 0, NULL, 0);  
  27.         if (IS_ERR(i2s->pdev)) {  
  28.             kfree(i2s);  
  29.             return NULL;  
  30.         }  
  31.     }  
  32.     /* Pre-assign snd_soc_dai_set_drvdata */  
  33.     dev_set_drvdata(&i2s->pdev->dev, i2s);  
  34.     return i2s;  
  35. }  

snd_pcm_open()的时候会先将snd_pcm_hardware的声明与cpu_dai声明做交集,然后在于codec_dai作交集

这个交集就是所选择dai_link的支持的pcm数据格式范围

最后tinyalsa会把用户选择的媒体格式数据pcm_config传下来,如下:

  1. struct pcm_config config = {  
  2.     channels : mChannelCount,  
  3.     rate : AUDIO_HW_IN_SAMPLERATE,  
  4.     period_size : AUDIO_HW_IN_PERIOD_SZ,  
  5.     period_count : AUDIO_HW_IN_PERIOD_CNT,  
  6.     format : PCM_FORMAT_S16_LE,  
  7.     start_threshold : 0,  
  8.     stop_threshold : 0,  
  9.     silence_threshold : 0,  
  10. };  

而先前说的那些rule就是检查用户请求的pcm_config是否在那个交集范围之内,不在说明格式不支持

如果我们确信格式支持,但是constraint检查不过,不用去看那些rule,直接查找我上面说的几个声明好了,肯定有某项不在交集范围之内

最后贴一段record开始之后的printk打印log,方便录音过程的理解:

  1. [   92.487014] wm8994-snd_pcm_capture_open   
  2. [   92.491048] wm8994-snd_pcm_open   
  3. [   92.494080] wm8994-snd_pcm_hw_rule_add   
  4. [   92.497903] wm8994-snd_pcm_hw_rule_add   
  5. [   92.501719] wm8994-snd_pcm_hw_rule_add   
  6. [   92.505538] wm8994-snd_pcm_hw_rule_add   
  7. [   92.509346] wm8994-snd_pcm_hw_rule_add   
  8. [   92.513176] wm8994-snd_pcm_hw_rule_add   
  9. [   92.516996] wm8994-snd_pcm_hw_rule_add   
  10. [   92.520868] wm8994-snd_pcm_hw_rule_add   
  11. [   92.524622] wm8994-snd_pcm_hw_rule_add   
  12. [   92.528455] wm8994-snd_pcm_hw_rule_add   
  13. [   92.532273] wm8994-snd_pcm_hw_rule_add   
  14. [   92.536091] wm8994-snd_pcm_hw_rule_add   
  15. [   92.539899] wm8994-snd_pcm_hw_rule_add   
  16. [   92.543730] wm8994-snd_pcm_hw_rule_add   
  17. [   92.547549] wm8994-snd_pcm_hw_rule_add   
  18. [   92.551397] wm8994-snd_pcm_hw_rule_add   
  19. [   92.555219] wm8994-snd_pcm_hw_rule_add   
  20. [   92.558996] wm8994-snd_pcm_hw_rule_add   
  21. [   92.562829] wm8994-snd_pcm_hw_rule_add   
  22. [   92.566646] wm8994-snd_pcm_hw_rule_add   
  23. [   92.570469] Entered dma_open  
  24. [   92.573325]  WM8994 AIF1: Symmetry forces 44100Hz rate  
  25. [   92.578452] wm8994-snd_interval_refine   
  26. [   92.582271] wm8994-snd_interval_refine   
  27. [   92.586089] wm8994-snd_interval_refine   
  28. [   92.589896] wm8994-snd_interval_refine   
  29. [   92.593873] wm8994-snd_interval_refine   
  30. [   92.597546] wm8994-snd_interval_refine   
  31. [   92.601366] wm8994-snd_pcm_hw_rule_add   
  32. [   92.605184] wm8994-snd_pcm_hw_rule_add   
  33. [   92.608998] wm8994-snd_pcm_capture_ioctl   
  34. [   92.613002] wm8994-snd_pcm_lib_ioctl cmd 0x1  
  35. [   92.617252] wm8994-snd_pcm_capture_ioctl   
  36. [   92.621296] wm8994-snd_interval_refine   
  37. [   92.625064] wm8994-snd_interval_refine   
  38. [   92.628870] wm8994-snd_interval_refine   
  39. [   92.632701] wm8994-snd_interval_refine   
  40. .........................................  
  41. [   92.766374] wm8994-snd_interval_refine   
  42. [   92.770192] wm8994-snd_interval_refine   
  43. [   92.774000] wm8994-snd_interval_refine   
  44. [   92.777831] wm8994-snd_interval_refine   
  45. [   92.781651] wm8994-snd_pcm_lib_ioctl cmd 0x4  
  46. [   92.785906] wm8994-snd_interval_refine   
  47. [   92.789711] wm8994-snd_interval_refine   
  48. [   92.793736] wm8994-snd_interval_refine   
  49. [   92.797361] wm8994-snd_interval_refine   
  50. [   92.801180] wm8994-snd_interval_refine   
  51. [   92.804987] wm8994-snd_interval_refine   
  52. [   92.808819] wm8994-snd_interval_refine   
  53. [   92.812638] wm8994-snd_interval_refine   
  54. [   92.816456] wm8994-snd_interval_refine   
  55. [   92.820320] wm8994-snd_interval_refine   
  56. [   92.824084] wm8994-snd_interval_refine   
  57. [   92.827917] wm8994-snd_interval_refine   
  58. [   92.831735] wm8994-snd_interval_refine   
  59. [   92.835553] wm8994-snd_interval_refine   
  60. [   92.839361] wm8994-snd_interval_refine   
  61. [   92.843191] wm8994-snd_interval_refine   
  62. [   92.847011] wm8994-snd_interval_refine   
  63. [   92.850857] wm8994-snd_interval_refine   
  64. [   92.854638] wm8994-snd_pcm_lib_ioctl cmd 0x4  
  65. [   92.858932] wm8994-snd_interval_refine   
  66. [   92.862725] wm8994-snd_pcm_lib_ioctl cmd 0x4  
  67. [   92.866977] wm8994-soc_pcm_hw_params   
  68. [   92.870621] wm8994-smdk_hw_params   
  69. [   92.873995] [zsb] wm8994_set_dai_fmt: id : 1  
  70. [   92.878262] wm8994-codec wm8994-codec: read 300 => 2010  
  71. [   92.883470] wm8994-codec wm8994-codec: read 302 => 4000  
  72. [   92.888676] wm8994-i2s_set_fmt   
  73. [   92.891945] [zsb] wm8994_set_fll  
  74. [   92.895003] wm8994-codec wm8994-codec: read 200 => 10  
  75. [   92.900050] wm8994-codec wm8994-codec: read 204 => 0  
  76. [   92.904982] [zsb] wm8994_set_dai_sysclk  
  77. [   92.908815] wm8994-codec wm8994-codec: AIF1 using FLL1  
  78. [   92.913934] [zsb] configure_clock  
  79. [   92.917233] [zsb] configure_aif_clock aif : 0, sysclk : 3  
  80. [   92.922664] wm8994-codec wm8994-codec: read 200 => 10  
  81. [   92.927652] [zsb] configure_aif_clock aif : 1, sysclk : 0  
  82. [   92.933033] wm8994-codec wm8994-codec: read 208 => 0  
  83. [   92.937979] [zsb] wm8994_hw_params  
  84. [   92.941365] wm8994-codec wm8994-codec: Sample rate is 44100Hz  
  85. [   92.947094] wm8994-codec wm8994-codec: AIF1CLK is 11289600Hz, target BCLK 1411200Hz  
  86. [   92.954760] wm8994-codec wm8994-codec: read 300 => 2010  
  87. [   92.959974] wm8994-codec wm8994-codec: Selected AIF1CLK/fs = 256  
  88. [   92.965933] wm8994-codec wm8994-codec: Using BCLK_DIV 80 for actual BCLK 1411200Hz  
  89. [   92.973482] wm8994-codec wm8994-codec: Using LRCLK rate 32 for actual LRCLK 44100Hz  
  90. [   92.981123] wm8994-codec wm8994-codec: read 300 => 2010  
  91. [   92.986327] wm8994-codec wm8994-codec: read 301 => 4000  
  92. [   92.991715] wm8994-codec wm8994-codec: read 303 => 70  
  93. [   92.996570] wm8994-codec wm8994-codec: read 305 => 20  
  94. [   93.001604] wm8994-codec wm8994-codec: read 210 => 73  
  95. [   93.006639] wm8994-i2s_hw_params   
  96. [   93.009925] Entered dma_hw_params  
  97. [   93.013236] params e00eadc0, client e00eadc0, channel 15  
  98. [   93.018596] snd_pcm_set_runtime_buffer dma_area 0xffd60000 dma_addr 0x60600000   
  99. [   93.025870] DmaAddr=@60600000 Total=8192bytes PrdSz=2 #Prds=4096 dma_area=0xffd60000  
  100. [   93.033556] wm8994-snd_pcm_capture_ioctl   
  101. [   93.037539] wm8994-snd_pcm_sw_params_user   
  102. [   93.041639] wm8994-snd_pcm_mmap   
  103. [   93.044835] wm8994-snd_pcm_capture_ioctl   
  104. [   93.048869] snd_ctl_ioctl-cmd=0xc2c85512  
  105. [   93.052781] wm8994-codec wm8994-codec: read 28 => 30  
  106. [   93.057680] snd_ctl_ioctl-cmd=0xc2c85513  
  107. [   93.061630] wm8994-codec wm8994-codec: read 28 => 30  
  108. [   93.066553] snd_ctl_ioctl-cmd=0xc2c85512  
  109. [   93.070446] wm8994-codec wm8994-codec: read 28 => 30  
  110. [   93.075385] snd_ctl_ioctl-cmd=0xc2c85513  
  111. [   93.079283] wm8994-codec wm8994-codec: read 28 => 30  
  112. [   93.084246] snd_ctl_ioctl-cmd=0xc2c85512  
  113. [   93.088148] wm8994-codec wm8994-codec: read 18 => 10c  
  114. [   93.093324] snd_ctl_ioctl-cmd=0xc2c85513  
  115. [   93.097086] wm8994-codec wm8994-codec: read 18 => 10c  
  116. [   93.102126] snd_ctl_ioctl-cmd=0xc2c85512  
  117. [   93.106028] wm8994-codec wm8994-codec: read 18 => 10c  
  118. [   93.111059] snd_ctl_ioctl-cmd=0xc2c85513  
  119. [   93.114954] wm8994-codec wm8994-codec: read 18 => 10c  
  120. [   93.120079] snd_ctl_ioctl-cmd=0xc2c85512  
  121. [   93.123901] wm8994-codec wm8994-codec: read 29 => 30  
  122. [   93.128856] snd_ctl_ioctl-cmd=0xc2c85513  
  123. [   93.132764] wm8994-codec wm8994-codec: read 29 => 30  
  124. [   93.137716] snd_ctl_ioctl-cmd=0xc2c85512  
  125. [   93.141616] wm8994-codec wm8994-codec: read 29 => 30  
  126. [   93.146561] snd_ctl_ioctl-cmd=0xc2c85513  
  127. [   93.150496] wm8994-codec wm8994-codec: read 29 => 30  
  128. [   93.155429] snd_ctl_ioctl-cmd=0xc2c85512  
  129. [   93.159312] snd_ctl_ioctl-cmd=0xc2c85513  
  130. [   93.163271] snd_ctl_ioctl-cmd=0xc2c85512  
  131. [   93.167138] wm8994-codec wm8994-codec: read 300 => 2010  
  132. [   93.172341] snd_ctl_ioctl-cmd=0xc2c85513  
  133. [   93.176249] wm8994-codec wm8994-codec: read 300 => 2010  
  134. [   93.181464] snd_ctl_ioctl-cmd=0xc2c85512  
  135. [   93.185363] wm8994-codec wm8994-codec: read 300 => 2010  
  136. [   93.190755] snd_ctl_ioctl-cmd=0xc2c85513  
  137. [   93.194464] wm8994-codec wm8994-codec: read 300 => 2010  
  138. [   93.199691] snd_ctl_ioctl-cmd=0xc2c85512  
  139. [   93.203591] wm8994-codec wm8994-codec: read 400 => 1ee  
  140. [   93.208710] wm8994-codec wm8994-codec: read 401 => 1ee  
  141. [   93.213831] snd_ctl_ioctl-cmd=0xc2c85513  
  142. [   93.217738] wm8994-codec wm8994-codec: read 400 => 1ee  
  143. [   93.222903] wm8994-codec wm8994-codec: read 401 => 1ee  
  144. [   93.227981] snd_ctl_ioctl-cmd=0xc2c85512  
  145. [   93.231888] wm8994-codec wm8994-codec: read 400 => 1ee  
  146. [   93.237007] wm8994-codec wm8994-codec: read 401 => 1ee  
  147. [   93.242130] snd_ctl_ioctl-cmd=0xc2c85513  
  148. [   93.246036] wm8994-codec wm8994-codec: read 400 => 1ee  
  149. [   93.251182] wm8994-codec wm8994-codec: read 401 => 1ee  
  150. [   93.256291] snd_ctl_ioctl-cmd=0xc2c85512  
  151. [   93.260188] wm8994-codec wm8994-codec: read 440 => 9b  
  152. [   93.265246] snd_ctl_ioctl-cmd=0xc2c85513  
  153. [   93.269114] wm8994-codec wm8994-codec: read 440 => 9b  
  154. [   93.274159] wm8994-codec wm8994-codec: read 440 => 9b  
  155. [   93.279204] snd_ctl_ioctl-cmd=0xc2c85512  
  156. [   93.283101] wm8994-codec wm8994-codec: read 440 => 9b  
  157. [   93.288132] snd_ctl_ioctl-cmd=0xc2c85513  
  158. [   93.292182] wm8994-codec wm8994-codec: read 440 => 9b  
  159. [   93.297073] wm8994-codec wm8994-codec: read 440 => 9b  
  160. [   93.302121] snd_ctl_ioctl-cmd=0xc2c85512  
  161. [   93.306020] wm8994-codec wm8994-codec: read 606 => 2  
  162. [   93.310961] snd_ctl_ioctl-cmd=0xc2c85513  
  163. [   93.314858] wm8994-codec wm8994-codec: read 606 => 2  
  164. [   93.319828] snd_ctl_ioctl-cmd=0xc2c85512  
  165. [   93.323772] wm8994-codec wm8994-codec: read 607 => 2  
  166. [   93.328669] snd_ctl_ioctl-cmd=0xc2c85513  
  167. [   93.332578] wm8994-codec wm8994-codec: read 607 => 2  
  168. [   93.337562] wm8994-snd_pcm_capture_ioctl   
  169. [   93.341519] wm8994-soc_pcm_prepare   
  170. [   93.344975] Entered dma_prepare addr=0x03830014,size=2,start=0x60600000  
  171. [   93.351617] Entered dma_enqueue  
  172. [   93.354694] dma_enqueue: loaded 0, limit 2  
  173. [   93.358920] wm8994-codec wm8994-codec: read 208 => 0  
  174. [   93.364156] [zsb] wm8994_set_bias_level: 2  
  175. [   93.367849] wm8994-codec wm8994-codec: read 1 => 35  
  176. [   93.372676] wm8994-codec wm8994-codec: write 1 = 33  
  177. [   93.377537] wm8994-codec wm8994-codec: 0x0001 <- 0x0033  
  178. [   93.382920] [zsb] aif1clk_ev  
  179. [   93.385613] wm8994-codec wm8994-codec: read 208 => 0  
  180. [   93.390744] wm8994-codec wm8994-codec: write 208 = a  
  181. [   93.395503] wm8994-codec wm8994-codec: 0x0208 <- 0x000a  
  182. [   93.400884] wm8994-codec wm8994-codec: read 4 => 0  
  183. [   93.405486] wm8994-codec wm8994-codec: write 4 = 200  
  184. [   93.410433] wm8994-codec wm8994-codec: 0x0004 <- 0x0200  
  185. [   93.415810] wm8994-codec wm8994-codec: read 200 => 10  
  186. [   93.420680] wm8994-codec wm8994-codec: write 200 = 11  
  187. [   93.425763] wm8994-codec wm8994-codec: 0x0200 <- 0x0011  
  188. [   93.431090] wm8994-codec wm8994-codec: read 5 => 3  
  189. [   93.435917] wm8994-codec wm8994-codec: read 900 => 0  
  190. [   93.440640] wm8994-codec wm8994-codec: read 5 => 3  
  191. [   93.445615] wm8994-codec wm8994-codec: read 900 => 0  
  192. [   93.450366] wm8994-codec wm8994-codec: read 5 => 3  
  193. [   93.455367] wm8994-codec wm8994-codec: read 900 => 0  
  194. [   93.460148] wm8994-codec wm8994-codec: read 4 => 200  
  195. [   93.465032] wm8994-codec wm8994-codec: write 4 = 202  
  196. [   93.470026] wm8994-codec wm8994-codec: 0x0004 <- 0x0202  
  197. [   93.475346] wm8994-codec wm8994-codec: read 2 => 6000  
  198. [   93.480221] wm8994-codec wm8994-codec: write 2 = 6240  
  199. [   93.485254] wm8994-codec wm8994-codec: 0x0002 <- 0x6240  
  200. [   93.490784] [zsb] late_disable_ev  
  201. [   93.493950] wm8994-codec wm8994-codec: read 212 => 0  
  202. [   93.498709] wm8994-codec wm8994-codec: SRC status: 0  
  203. [   93.503678] [zsb] wm8994_set_bias_level: 3  
  204. [   93.507737] wm8994-codec wm8994-codec: read 1 => 33  
  205. [   93.512604] [zsb] wm8994_aif_mute id:1 mute:0  
  206. [   93.516938] wm8994-codec wm8994-codec: read 420 => 200  
  207. [   93.522114] wm8994-codec wm8994-codec: write 420 = 0  
  208. [   93.527007] wm8994-codec wm8994-codec: 0x0420 <- 0x0000  
  209. [   93.532384] wm8994-snd_pcm_lib_ioctl cmd 0x0  
  210. [   93.536476] wm8994-soc_pcm_prepare   
  211. [   93.539927] Entered idma_prepare start=0x02058000  
  212. [   93.544706] wm8994-codec wm8994-codec: read 208 => a  
  213. [   93.549899] wm8994-snd_pcm_capture_ioctl   
  214. [   93.553568] wm8994-soc_pcm_trigger   
  215. [   93.557025] Entered dma_trigger  
  216. [   93.560163] wm8994-i2s_trigger cmd=1 capture=1,i2s->addr=0xefc9e000  
  217. [   93.566409] wm8994-i2s_trigger I2SCON=0x8050ce53,I2SMOD=0xd0001900,I2SRXD=0x00000000  
  218. [   93.574202] wm8994-snd_pcm_capture_ioctl   
  219. [   93.578131] wm8994-snd_pcm_lib_read   
  220. [   93.580051] wm8994-codec wm8994-codec: read 1 => 33  
  221. [   93.580058] wm8994-codec wm8994-codec: write 1 = 333  
  222. [   93.580064] wm8994-codec wm8994-codec: 0x0001 <- 0x0333  
  223. [   93.596921] wm8994-snd_pcm_lib_read_transfer   
  224. [   93.601079] wm8994-snd_pcm_lib_read_transfer   
  225. [   93.605401] wm8994-codec wm8994-codec: read 60 => 0  
  226. [   93.605405] wm8994-snd_pcm_lib_read_transfer   
  227. [   93.605417] wm8994-snd_pcm_lib_read_transfer   
  228. [   93.612894] wm8994-snd_pcm_lib_read_transfer   
  229. [   93.613112] wm8994-snd_pcm_capture_ioctl   
  230. [   93.613117] wm8994-snd_pcm_lib_read   
  231. [   93.613126] wm8994-snd_pcm_lib_read_transfer   
  232. [   93.635181] wm8994-codec wm8994-codec: write 60 = 22  
  233. [   93.640111] wm8994-codec wm8994-codec: 0x0060 <- 0x0022  
  234. [   93.645496] wm8994-codec wm8994-codec: read 4c => 1f25  
  235. [   93.650440] wm8994-codec wm8994-codec: read 208 => a  
  236. [   93.655399] wm8994-codec wm8994-codec: write 208 = 1a  
  237. [   93.659331] wm8994-snd_pcm_lib_read_transfer   
  238. [   93.659624] wm8994-snd_pcm_release   
  239. [   93.659632] wm8994-soc_pcm_trigger   
  240. [   93.659636] Entered dma_trigger  
  241. [   93.659655] wm8994-i2s_trigger cmd=0 capture=1,i2s->addr=0xefc9e000  
  242. [   93.681094] wm8994-codec wm8994-codec: 0x0208 <- 0x001a  
  243. [   93.686451] wm8994-codec wm8994-codec: read 5 => 3  
  244. [   93.691059] wm8994-codec wm8994-codec: write 5 = 303  
  245. [   93.696020] wm8994-codec wm8994-codec: 0x0005 <- 0x0303  
  246. [   93.701376] wm8994-codec wm8994-codec: read 5 => 303  
  247. [   93.706387] wm8994-codec wm8994-codec: read 900 => 0  
  248. [   93.711110] wm8994-codec wm8994-codec: read 5 => 303  
  249. [   93.716260] wm8994-codec wm8994-codec: read 900 => 0  
  250. [   93.721006] wm8994-codec wm8994-codec: read 5 => 303  
  251. [   93.726155] wm8994-codec wm8994-codec: read 900 => 0  
  252. [   93.730915] wm8994-codec wm8994-codec: read 5 => 303  
  253. [   93.736057] wm8994-codec wm8994-codec: read 900 => 0  
  254. [   93.740796] wm8994-codec wm8994-codec: read 5 => 303  
  255. [   93.745966] wm8994-codec wm8994-codec: read 900 => 0  
  256. [   93.750691] wm8994-codec wm8994-codec: read 5 => 303  
  257. [   93.755839] wm8994-codec wm8994-codec: read 900 => 0  
  258. [   93.760586] [zsb] dac_ev  
  259. [   93.763090] wm8994-codec wm8994-codec: read 5 => 303  
  260. [   93.768062] [zsb] dac_ev  
  261. [   93.770568] wm8994-codec wm8994-codec: read 5 => 303  
  262. [   93.775517] wm8994-codec wm8994-codec: read 3 => 0  
  263. [   93.780302] wm8994-codec wm8994-codec: write 3 = 300  
  264. [   93.785238] wm8994-codec wm8994-codec: 0x0003 <- 0x0300  
  265. [   93.790670] wm8994-codec wm8994-codec: read 5 => 303  
  266. [   93.795604] wm8994-codec wm8994-codec: read 900 => 0  
  267. [   93.800341] wm8994-codec wm8994-codec: read 5 => 303  
  268. [   93.805516] wm8994-codec wm8994-codec: read 900 => 0  
  269. [   93.810237] wm8994-codec wm8994-codec: read 5 => 303  
  270. [   93.815388] wm8994-codec wm8994-codec: read 900 => 0  
  271. [   93.820133] wm8994-codec wm8994-codec: read 5 => 303  
  272. [   93.825279] wm8994-codec wm8994-codec: read 900 => 0  
  273. [   93.830040] wm8994-codec wm8994-codec: read 5 => 303  
  274. [   93.835171] wm8994-codec wm8994-codec: read 900 => 0  
  275. [   93.839908] wm8994-codec wm8994-codec: read 5 => 303  
  276. [   93.845098] wm8994-codec wm8994-codec: read 900 => 0  
  277. [   93.849805] wm8994-codec wm8994-codec: read 60 => 22  
  278. [   93.854764] wm8994-codec wm8994-codec: read 4c => 1f25  
  279. [   93.859898] wm8994-codec wm8994-codec: write 4c = 9f25  
  280. [   93.865022] wm8994-codec wm8994-codec: 0x004c <- 0x9f25  
  281. [   93.880031] wm8994-codec wm8994-codec: read 1 => 333  
  282. [   93.880107] wm8994-codec wm8994-codec: write 60 = 22  
  283. [   93.884320] wm8994-codec wm8994-codec: 0x0060 <- 0x0022  
  284. [   93.889679] wm8994-codec wm8994-codec: read 55 => 401  
  285. [   93.894568] wm8994-codec wm8994-codec: Using cached DC servo offset fbfb  
  286. [   93.901237] wm8994-codec wm8994-codec: write 57 = fbfb  
  287. [   93.906371] wm8994-codec wm8994-codec: 0x0057 <- 0xfbfb  
  288. [   93.911725] wm8994-codec wm8994-codec: write 54 = f  
  289. [   93.916440] wm8994-codec wm8994-codec: 0x0054 <- 0x000f  
  290. [   93.921793] wm8994-codec wm8994-codec: Waiting for DC servo...  
  291. [   93.935231] wm8994-codec wm8994-codec: read 54 => 3  
  292. [   93.935305] wm8994-codec wm8994-codec: DC servo: 3  
  293. [   93.939255] wm8994-codec wm8994-codec: write 60 = ee  
  294. [   93.944195] wm8994-codec wm8994-codec: 0x0060 <- 0x00ee  
  295. [   93.949574] wm8994-codec wm8994-codec: read 1 => 333  
  296. [   93.954350] wm8994-codec wm8994-codec: write 1 = 3333  
  297. [   93.959384] wm8994-codec wm8994-codec: 0x0001 <- 0x3333  
  298. [   93.964761] [zsb] late_disable_ev  
  299. [   93.968099] wm8994-codec wm8994-codec: read 212 => 0  
  300. [   93.972837] wm8994-codec wm8994-codec: SRC status: 0  
  301. [   93.977820] [zsb] wm8994_aif_mute id:1 mute:0  
  302. [   93.982127] wm8994-codec wm8994-codec: read 420 => 0  
  303. [   93.987075] wm8994-snd_pcm_lib_ioctl cmd 0x0  
  304. [   93.987082] Entered dma_hw_free  
  305. [   93.987106] Entered dma_close  
  306. [   93.987193] wm8994-codec wm8994-codec: read 208 => 1a  
  307. [   93.987549] wm8994-codec wm8994-codec: read 2 => 6240  
  308. [   93.987555] wm8994-codec wm8994-codec: write 2 = 6000  
  309. [   93.987561] wm8994-codec wm8994-codec: 0x0002 <- 0x6000  
  310. [   93.987725] wm8994-codec wm8994-codec: read 4 => 202  
  311. [   93.987730] wm8994-codec wm8994-codec: write 4 = 200  
  312. [   93.987736] wm8994-codec wm8994-codec: 0x0004 <- 0x0200  
  313. [   93.987897] wm8994-codec wm8994-codec: read 4 => 200  
  314. [   93.987903] wm8994-codec wm8994-codec: write 4 = 0  
  315. [   93.987909] wm8994-codec wm8994-codec: 0x0004 <- 0x0000  
  316. [   93.988066] [zsb] late_disable_ev  
  317. [   93.988272] wm8994-codec wm8994-codec: read 212 => 0  
  318. [   93.988277] wm8994-codec wm8994-codec: SRC status: 0  
  319. [   94.060961] wm8994-snd_pcm_lib_write   
  320. [   94.064577] wm8994-snd_pcm_lib_write_transfer   
  321. [   94.069362] wm8994-snd_pcm_lib_write   
  322. [   94.072766] wm8994-snd_pcm_lib_write_transfer   
  323. [   94.077304] wm8994-soc_pcm_trigger   
  324. [   94.080552] Entered idma_trigger  
  325. [   94.083772] wm8994-i2s_trigger cmd=1 capture=0,i2s->addr=0xefcb2000  
  326. [   94.090270] wm8994-snd_pcm_lib_write   
  327. [   94.093658] wm8994-snd_pcm_lib_write_transfer   
  328. [   94.098399] wm8994-snd_pcm_lib_write   
  329. [   94.102092] wm8994-snd_pcm_lib_write_transfer   
  330. [   94.129519] wm8994-snd_pcm_lib_write   
  331. [   94.129583] wm8994-snd_pcm_lib_write_transfer   
  332. [   94.132253] wm8994-snd_pcm_lib_write_transfer   
  333. [   94.136440] wm8994-snd_pcm_lib_write_transfer   
  334. ................................................  
  335. [   97.091836] wm8994-snd_pcm_lib_write   
  336. [   97.091894] wm8994-snd_pcm_lib_write_transfer   
  337. [   97.094403] wm8994-snd_pcm_lib_write_transfer   
  338. [   97.098725] wm8994-snd_pcm_lib_write_transfer   
  339. [   97.103158] wm8994-snd_pcm_lib_write_transfer   
  340. [   97.107587] wm8994-snd_pcm_lib_write_transfer   
  341. [   97.112147] wm8994-snd_pcm_release   
  342. [   97.115472] wm8994-soc_pcm_trigger   
  343. [   97.118926] Entered idma_trigger  
  344. [   97.122141] wm8994-i2s_trigger cmd=0 capture=0,i2s->addr=0xefcb2000  
  345. [   97.128414] Entered idma_hw_free  
  346. [   97.131611] [zsb] wm8994_aif_mute id:1 mute:1  
  347. [   97.135962] wm8994-codec wm8994-codec: read 420 => 0  
  348. [   97.140897] wm8994-codec wm8994-codec: write 420 = 200  
  349. [   97.146020] wm8994-codec wm8994-codec: 0x0420 <- 0x0200  
  350. [   97.151405] Entered idma_close, prtd = d7cf9f40  

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的录音机APP的实现步骤: 1. 在 Android Studio 中创建一个空白项目,并在布局文件中添加一个按钮和一个文本框用于显示录音时长。 2. 添加权限 在 AndroidManifest.xml 文件中添加以下权限: ``` <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 3. 创建录音机类 创建一个名为 `SoundRecorder` 的 Java 类,该类用于管理录音的开始、停止、暂停和继续等操作。 ```java public class SoundRecorder { private MediaRecorder mRecorder; private String mFileName; private long mStartTime; public SoundRecorder(String fileName) { mFileName = fileName; mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mRecorder.setOutputFile(mFileName); } public void start() { try { mRecorder.prepare(); mRecorder.start(); mStartTime = System.currentTimeMillis(); } catch (IOException e) { Log.e("SoundRecorder", "prepare() failed"); } } public void pause() { mRecorder.pause(); } public void resume() { mRecorder.resume(); } public void stop() { mRecorder.stop(); mRecorder.release(); mRecorder = null; } public int getDuration() { return (int) (System.currentTimeMillis() - mStartTime) / 1000; } } ``` 4. 在 Activity 中调用录音机类 在 Activity 中创建一个 `SoundRecorder` 实例,并在按钮的点击事件中调用录音机的开始、停止、暂停和继续等方法,并在文本框中显示录音时长。 ```java public class MainActivity extends AppCompatActivity { private Button mRecordButton; private TextView mDurationTextView; private SoundRecorder mRecorder; private boolean mIsRecording = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecordButton = findViewById(R.id.record_button); mDurationTextView = findViewById(R.id.duration_text_view); mRecordButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mIsRecording) { mRecorder.stop(); mIsRecording = false; mRecordButton.setText("Record"); } else { mRecorder = new SoundRecorder(getExternalCacheDir().getAbsolutePath() + "/recording.3gp"); mRecorder.start(); mIsRecording = true; mRecordButton.setText("Stop"); new CountDownTimer(Long.MAX_VALUE, 1000) { @Override public void onTick(long millisUntilFinished) { mDurationTextView.setText(String.format("%02d:%02d", mRecorder.getDuration() / 60, mRecorder.getDuration() % 60)); } @Override public void onFinish() { } }.start(); } } }); } } ``` 这样你就可以在 Android Studio 中创建一个简单的录音机APP了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值