搜索
bottom↓
回复: 14

和大家分享一下SpeexLib使用中的一些小技巧

[复制链接]

出0入0汤圆

发表于 2013-12-20 15:29:57 | 显示全部楼层 |阅读模式
好久没有发帖了,今天闲下来,和大家分享一下自己研究了大半年的Speex语音压缩库。自己水平也不咋样,如果有讲错的地方还望大家指出来,大家一起学习,这个帖子我会以连载的方式来写,好进入正题:
1,:先讲一讲这个东西怎么用
    其实讲到这里,很多人都会想到ST有提供的现成的基于F103系列的库,没错我就是从这个库里面研究起来的,这个库有他的优点:ST专门对几个滤波器函数优化过,使用汇编写的,删除了一些子模式,并且使用定点运算,再这里先贴一下被ST优化过得那几个函数名称:filter_mem16(), inner_prod(),vq_nbest()等等,之所以这样才得以在103上面可以运行起来,缺点嘛:就是被阉割过了,只能使用一个模式,你如果想要更高的语音质量就别想用这个库了,它里面默认的质量是4,最好的质量等级是10,,具体的可以看下面的那个结构体:

初始值

其实如果真做语音压缩一类的话,我推荐用F407,开启FPU。或者DSP,优点嘛有很多,其中我认为最有用的就是里面的VBR了,可以做动态变比,也就是当你有语音信息的时候就会编出比较多的数据,没有语音信息时编出的数据非常少,只有1个Byte,这个也就引出了后面的DTX,它的意思就是说你没有语音信号的时候可以不传数据,想想这是不是很方便呢。好这个先提到这里,后面还有预处理什么的,这个VBR就放到后面来讲。有了上面这些参数的定义我们可以初始化到Speex里面去了,可以这样操作:

在这里特别提醒一下大家,这个库使用了一些内存分配,需要从堆里面去开辟内存,所以你的程序如果一运行到初始化就进入硬件错误,没关系,堆开大点就好了,一般对于编码解码来说 :0x8000的大小就可以了。后面说说怎么编码吧:

这里注意这个Nbyte,不要被ST提供的那个库给迷惑了,正确的用法是这样。
解码是这样:

这里有一些代码是用于缓存语音的,所以自己写了一个环形队列,为了方便大家阅读,我把代码贴出来:
  1. /**
  2.   ******************************************************************************
  3.   * @file    MemQueue.C
  4.   * @author  Luoxianhui R&D Driver Software Team
  5.   * @version V1.0.0
  6.   * @date    06/09/2013
  7.   * @brief   MemQueue»·ÐζÓÁлº´æ
  8.   ******************************************************************************
  9. **/
  10.   
  11. /* Includes ------------------------------------------------------------------*/
  12. #include "MemQueue.h"
  13. #include "define.h"
  14. #include "includes.h"
  15. /** @addtogroup MemQueue_Driver
  16.   * @{
  17.   */

  18. /** @addtogroup Mem
  19.   * @{
  20.   */

  21. /* Private typedef -----------------------------------------------------------*/
  22. /* Private define ------------------------------------------------------------*/
  23. /* Private macro -------------------------------------------------------------*/
  24. /* Private variables ---------------------------------------------------------*/
  25. SqQueueChar TestQueue;
  26. // SqQueueChar RxQueue;
  27. // SqQueueChar TxQueue;
  28. SqJitterQueueChar RxQueue;


  29. SqQueueShort AdQueue;
  30. SqQueueShort DaQueue;
  31. /* Private function prototypes -----------------------------------------------*/
  32. /* Private functions ---------------------------------------------------------*/
  33. void InitQueueChar(SqQueueChar *Q, INT32U F, INT32U E);
  34. INT16U QueueLenthChar(SqQueueChar *Q);
  35. SqQueueSta EnQueueChar(SqQueueChar *Q, INT8U Data);
  36. SqQueueSta DeQueueChar(SqQueueChar *Q, INT8U *Data);
  37. SqQueueSta EnQueueStrChar(SqQueueChar *Q, INT8U *Data,INT16U No);
  38. SqQueueSta DeQueueStrChar(SqQueueChar *Q, INT8U *Data,INT16U No);

  39. void InitQueueShort(SqQueueShort *Q, INT32U F, INT32U E);
  40. INT16U QueueLenthShort(SqQueueShort *Q);
  41. SqQueueSta EnQueueShort(SqQueueShort *Q, INT16S Data);
  42. SqQueueSta DeQueueShort(SqQueueShort *Q, INT16S *Data);
  43. SqQueueSta EnQueueStrShort(SqQueueShort *Q, INT16S *Data,INT16U No);
  44. SqQueueSta DeQueueStrShort(SqQueueShort *Q, INT16S *Data,INT16U No);


  45. void InitJitterQueueChar(SqJitterQueueChar *Q, INT32U F, INT32U E);
  46. INT16U JitterQueueLenthChar(SqJitterQueueChar *Q);
  47. SqQueueSta DeJitterQueueChar(SqJitterQueueChar *Q, INT8U *Data, INT16U *No);
  48. SqQueueSta EnJitterQueueChar(SqJitterQueueChar *Q, INT8U *Data, INT16U No);


  49. void InitQueueShort(SqQueueShort *Q, INT32U F, INT32U E)
  50. {
  51.         Q->sRear  = 0;
  52.         Q->sFront = 0;
  53.         Q->BufFullShortScal = F;
  54.         Q->BufEmptyShortScal = E;
  55.        
  56. }


  57. INT16U QueueLenthShort(SqQueueShort *Q)
  58. {
  59.         return(((Q->sRear) - (Q->sFront) + BufSizeShort) % BufSizeShort);
  60. }


  61. SqQueueSta EnQueueShort(SqQueueShort *Q, INT16S Data)
  62. {
  63.         if((((Q->sRear)+1) % BufSizeShort) ==  (Q->sFront))  return FALSE;
  64.         (*Q).gBuf[Q->sRear] = Data;
  65.         Q->sRear = (Q->sRear + 1) % BufSizeShort;
  66.         return TRUE;
  67. }


  68. SqQueueSta DeQueueShort(SqQueueShort *Q, INT16S *Data)
  69. {
  70.         if(Q->sRear == Q->sFront) return FALSE;
  71.        
  72.         *Data = (*Q).gBuf[Q->sFront];
  73.         Q->sFront = (Q->sFront + 1) % BufSizeShort;
  74.         return TRUE;
  75. }

  76. SqQueueSta EnQueueStrShort(SqQueueShort *Q, INT16S *Data,INT16U No)
  77. {
  78.         OS_CPU_SR cpu_sr=0;

  79.         INT16U i = 0;
  80.         INT16U Len = 0;


  81.         Len = QueueLenthShort(Q);
  82.         if(Len >= Q->BufFullShortScal)
  83.         {
  84.                 Q->BufEmpty = BufFull;
  85.         }
  86.         if(Len <= Q->BufEmptyShortScal)
  87.         {
  88.                 Q->BufEmpty = BufEmpty;
  89.         }
  90.         if( Len >= (BufSizeShort-No)) return FALSE;       
  91.         OS_ENTER_CRITICAL();
  92.         for(i=0; i<No; i++)
  93.   {
  94.                 EnQueueShort(Q,Data[i]);
  95.   }       
  96.         OS_EXIT_CRITICAL();
  97.         return TRUE;
  98.        
  99. }

  100. SqQueueSta DeQueueStrShort(SqQueueShort *Q, INT16S *Data,INT16U No)
  101. {
  102.         INT16U i = 0;
  103.         INT16U Len = 0;
  104.         OS_CPU_SR cpu_sr=0;
  105.         Len = QueueLenthShort(Q);
  106.         if(Len >= Q->BufFullShortScal)
  107.         {
  108.                 Q->BufEmpty = BufFull;
  109.         }
  110.         if(Len <= Q->BufEmptyShortScal)
  111.         {
  112.                 Q->BufEmpty = BufEmpty;
  113.         }
  114.         if(Len <= No) return FALSE;
  115.   OS_ENTER_CRITICAL();
  116.         for(i=0; i<No; i++)
  117.         {       
  118.           DeQueueShort(Q,&(Data[i]));
  119.         }
  120.         OS_EXIT_CRITICAL();
  121.         return TRUE;
  122. }

  123. void InitQueueChar(SqQueueChar *Q, INT32U F, INT32U E)
  124. {
  125.         Q->sRear  = 0;
  126.         Q->sFront = 0;
  127.         Q->BufFullCharScal = F;
  128.         Q->BufEmptyCharScal = E;
  129. }


  130. INT16U QueueLenthChar(SqQueueChar *Q)
  131. {
  132.         return(((Q->sRear) - (Q->sFront) + BufSizeChar) % BufSizeChar);
  133. }


  134. SqQueueSta EnQueueChar(SqQueueChar *Q, INT8U Data)
  135. {
  136.         if((((Q->sRear)+1) % BufSizeChar) ==  (Q->sFront))  return FALSE;
  137.         (*Q).gBuf[Q->sRear] = Data;
  138.         Q->sRear = (Q->sRear + 1) % BufSizeChar;
  139.         return TRUE;
  140. }


  141. SqQueueSta DeQueueChar(SqQueueChar *Q, INT8U *Data)
  142. {
  143.         if(Q->sRear == Q->sFront) return FALSE;
  144.        
  145.         *Data = (*Q).gBuf[Q->sFront];
  146.         Q->sFront = (Q->sFront + 1) % BufSizeChar;
  147.         return TRUE;
  148. }

  149. SqQueueSta EnQueueStrChar(SqQueueChar *Q, INT8U *Data,INT16U No)
  150. {
  151.         INT16U i = 0;
  152.         INT16U Len = 0;
  153.         OS_CPU_SR cpu_sr=0;
  154.         Len = QueueLenthChar(Q);
  155.         if(Len >= Q->BufFullCharScal)
  156.         {
  157.                 Q->BufEmpty = BufFull;
  158.         }
  159.         if(Len <= Q->BufEmptyCharScal)
  160.         {
  161.                 Q->BufEmpty = BufEmpty;
  162.         }
  163.         if(Len >= (BufSizeChar-No)) return FALSE;       
  164.         OS_ENTER_CRITICAL();
  165.         for(i=0; i<No; i++)
  166.   {
  167.                 EnQueueChar(Q,Data[i]);
  168.   }       
  169.         OS_EXIT_CRITICAL();
  170.         return TRUE;
  171. }

  172. SqQueueSta DeQueueStrChar(SqQueueChar *Q, INT8U *Data,INT16U No)
  173. {
  174.         INT16U i = 0;
  175.         INT16U Len = 0;
  176.         OS_CPU_SR cpu_sr=0;
  177.         Len = QueueLenthChar(Q);
  178.         if(Len >= Q->BufFullCharScal)
  179.         {
  180.                 Q->BufEmpty = BufFull;
  181.         }
  182.         if(Len <= Q->BufEmptyCharScal)
  183.         {
  184.                 Q->BufEmpty = BufEmpty;
  185.         }
  186.         if(Len <= No) return FALSE;
  187.   OS_ENTER_CRITICAL();
  188.         for(i=0; i<No; i++)
  189.         {       
  190.           DeQueueChar(Q,&(Data[i]));
  191.         }
  192.         OS_EXIT_CRITICAL();  
  193.         return TRUE;
  194. }






  195. void InitJitterQueueChar(SqJitterQueueChar *Q, INT32U F, INT32U E)
  196. {
  197.         Q->sRear  = 0;
  198.         Q->sFront = 0;
  199.         Q->BufFullJitterCharScal = F;
  200.         Q->BufEmptyJitterCharScal = E;
  201. }


  202. INT16U JitterQueueLenthChar(SqJitterQueueChar *Q)
  203. {
  204.         return(((Q->sRear) - (Q->sFront) + BufSizeJitterChar) % BufSizeJitterChar);
  205. }


  206. SqQueueSta EnJitterQueueChar(SqJitterQueueChar *Q, INT8U *Data, INT16U No)
  207. {
  208.         INT16U i = 0;
  209.         INT16U Len = 0;
  210.         if((((Q->sRear)+1) % BufSizeJitterChar) ==  (Q->sFront))  return FALSE;
  211.        
  212.         Len = JitterQueueLenthChar(Q);
  213.        
  214.         if(Len >= Q->BufFullJitterCharScal)
  215.         {
  216.                 Q->BufEmpty = BufFull;
  217.         }
  218.         if(Len <= Q->BufEmptyJitterCharScal)
  219.         {
  220.                 Q->BufEmpty = BufEmpty;
  221.         }
  222.        
  223.         (*Q).gBuf[Q->sRear][0] = No;
  224.         for(i=0; i<No; i++)
  225.   {
  226.          (*Q).gBuf[Q->sRear][i + 1] = Data[i];
  227.         }
  228.         Q->sRear = (Q->sRear + 1) % BufSizeJitterChar;
  229.         return TRUE;
  230. }


  231. SqQueueSta DeJitterQueueChar(SqJitterQueueChar *Q, INT8U *Data, INT16U *No)
  232. {
  233.         INT16U i = 0;
  234.         INT16U Len = 0;
  235.         if(Q->sRear == Q->sFront) return FALSE;
  236.        
  237.         Len = JitterQueueLenthChar(Q);
  238.        
  239.         if(Len >= Q->BufFullJitterCharScal)
  240.         {
  241.                 Q->BufEmpty = BufFull;
  242.         }
  243.         if(Len <= Q->BufEmptyJitterCharScal)
  244.         {
  245.                 Q->BufEmpty = BufEmpty;
  246.         }
  247.         *No = (*Q).gBuf[Q->sFront][0];
  248.         for(i=0; i<(*Q).gBuf[Q->sFront][0]; i++)
  249.         {
  250.                 Data[i] = (*Q).gBuf[Q->sFront][i + 1];
  251.         }
  252.         Q->sFront = (Q->sFront + 1) % BufSizeJitterChar;
  253.         return TRUE;
  254. }

复制代码





下面是头文件




  1. #ifndef _MEMQUEUE_H_
  2. #define _MEMQUEUE_H_

  3. #include "define.h"

  4. #define BufSizeChar    2160
  5. #define BufSizeShort   3200

  6. #define BufFullChar     BufSizeChar - 920
  7. #define BufFullShort    BufSizeShort - 960

  8. #define BufEmptyChar     60
  9. #define BufEmptyShort    640


  10. #define BufSizeJitterChar     250
  11. #define FramSizeJitterChar    70

  12. #define BufFullJitterChar     BufSizeJitterChar - 200
  13. #define BufEmptyJitterChar     10



  14. typedef enum {FALSE, TRUE, BufFull, BufEmpty} SqQueueSta;



  15. typedef struct _SqJitterQueueChar
  16. {
  17.         INT8U  gBuf[BufSizeJitterChar][FramSizeJitterChar];

  18.         INT16U  sFront;
  19.         INT16U  sRear;
  20.         INT32U  BufFullJitterCharScal;
  21.         INT32U  BufEmptyJitterCharScal;
  22.   SqQueueSta BufEmpty;       
  23. }SqJitterQueueChar;


  24. typedef struct _SqQueueChar
  25. {
  26.         INT8U  gBuf[BufSizeChar];

  27.         INT16U  sFront;
  28.         INT16U  sRear;
  29.         INT32U  BufFullCharScal;
  30.         INT32U  BufEmptyCharScal;
  31.   SqQueueSta BufEmpty;       
  32. }SqQueueChar;


  33. typedef struct _SqQueueShort
  34. {
  35.         INT16S  gBuf[BufSizeShort];

  36.         INT16U  sFront;
  37.         INT16U  sRear;       
  38.         INT32U  BufFullShortScal;
  39.         INT32U  BufEmptyShortScal;
  40.         SqQueueSta BufEmpty;
  41.        
  42. }SqQueueShort;


  43. extern SqQueueChar TestQueue;
  44. // extern SqQueueChar RxQueue;
  45. // extern SqQueueChar TxQueue;
  46. extern SqJitterQueueChar RxQueue;
  47. // extern SqJitterQueueChar TxQueue;

  48. extern SqQueueShort AdQueue;
  49. extern SqQueueShort DaQueue;

  50. void InitQueueChar(SqQueueChar *Q, INT32U F, INT32U E);
  51. INT16U QueueLenthChar(SqQueueChar *Q);
  52. SqQueueSta EnQueueChar(SqQueueChar *Q, INT8U Data);
  53. SqQueueSta DeQueueChar(SqQueueChar *Q, INT8U *Data);
  54. SqQueueSta EnQueueStrChar(SqQueueChar *Q, INT8U *Data,INT16U No);
  55. SqQueueSta DeQueueStrChar(SqQueueChar *Q, INT8U *Data,INT16U No);

  56. void InitQueueShort(SqQueueShort *Q, INT32U F, INT32U E);
  57. INT16U QueueLenthShort(SqQueueShort *Q);
  58. SqQueueSta EnQueueShort(SqQueueShort *Q, INT16S Data);
  59. SqQueueSta DeQueueShort(SqQueueShort *Q, INT16S *Data);
  60. SqQueueSta EnQueueStrShort(SqQueueShort *Q, INT16S *Data,INT16U No);
  61. SqQueueSta DeQueueStrShort(SqQueueShort *Q, INT16S *Data,INT16U No);


  62. void InitJitterQueueChar(SqJitterQueueChar *Q, INT32U F, INT32U E);
  63. INT16U JitterQueueLenthChar(SqJitterQueueChar *Q);
  64. SqQueueSta DeJitterQueueChar(SqJitterQueueChar *Q, INT8U *Data, INT16U *No);
  65. SqQueueSta EnJitterQueueChar(SqJitterQueueChar *Q, INT8U *Data, INT16U No);

  66. #endif

复制代码


好今天先说到这里,后续,希望对大家有用。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-12-20 16:18:06 | 显示全部楼层

出0入0汤圆

发表于 2013-12-26 09:53:52 | 显示全部楼层
真的很有用,马上要做个声音强度检测的设备应该会用到

出0入0汤圆

发表于 2013-12-26 12:39:41 | 显示全部楼层
#在这里快速回复#谢谢分享

出0入17汤圆

发表于 2014-1-3 22:48:08 | 显示全部楼层

收下,谢谢!

出0入0汤圆

发表于 2014-3-31 11:06:35 | 显示全部楼层
可以发一个工程文件出来么?

出0入0汤圆

发表于 2014-4-1 11:16:57 | 显示全部楼层
感谢这样的分享

出100入101汤圆

发表于 2014-4-28 20:43:20 | 显示全部楼层
后续还有么?

出0入0汤圆

 楼主| 发表于 2014-4-28 20:48:36 | 显示全部楼层

有,等我有时间一点点的写。

出0入0汤圆

发表于 2014-9-19 00:17:48 | 显示全部楼层
关于speex的问题 急需请教  我是个学生 QQ812377513 恳请楼主给个Q或劳烦加我下  真心求教 真心谢过了

出0入0汤圆

发表于 2014-9-19 08:01:18 | 显示全部楼层
这个不错,上次玩了玩,但没做无线传输。不知道这个做出来用于对讲机效果怎么样。

出0入0汤圆

发表于 2014-9-19 08:16:35 | 显示全部楼层
wangweigang0 发表于 2014-9-19 08:01
这个不错,上次玩了玩,但没做无线传输。不知道这个做出来用于对讲机效果怎么样。 ...

在么  speex 问题请教

出0入0汤圆

发表于 2014-9-19 08:37:08 | 显示全部楼层
我的 问题 及 对应的程序 整理到 附件中的压缩文件里了  谁帮忙看下 指点下   正在一个人苦苦摸索的小白  谢谢 各位了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-9-19 09:11:36 | 显示全部楼层
刚才的附件 有文字遗漏  重新发一个

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2017-8-25 09:52:56 | 显示全部楼层
好的,谢谢,正在研究无线语音
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-21 23:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表