0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【潤和軟件DAYU200開發(fā)板體驗】移植speexdsp到OpenHarmony標準系統(tǒng)⑤

開發(fā)板試用精選 ? 來源:開發(fā)板試用 ? 作者:電子發(fā)燒友論壇 ? 2022-10-12 10:09 ? 次閱讀

本文來源電子發(fā)燒友社區(qū),作者:離北況歸, 帖子地址:https://bbs.elecfans.com/jishu_2308799_1_1.html


由于想要分享的內(nèi)容較多,為避免讀者姥爺們失去看下去的耐心,分享將以連載的方式進行。感謝潤和軟件提供的硬件支持。
下期預(yù)告:OAT開源掃描和三方庫上倉基本要求

本期為移植speexdspOpenHarmony標準系統(tǒng)的第⑤期,主要內(nèi)容如下:

image.png


speexdsp移植后已提交至openhamrony sig倉庫:https://gitee.com/openharmony-sig/contest/tree/master/2022_OpenHarmony_thirdparty/speexdsp


七、Speexdsp功能分析

  • 將speexdsp加入openharmony編譯體系后,能成功編譯出來動態(tài)鏈接庫和測試用的可執(zhí)行文件,并不代表移植三方庫成功。還要在開發(fā)板上運行測試其功能是否正常。

speexdsp核心庫分析

1.庫實現(xiàn)方式

2.依賴分析

  • 除C標準庫外,無其他第三方庫依賴

3.license以及版權(quán)

  • 根據(jù)speex官網(wǎng)https://speex.org/的信息,speexdsp使用的開源協(xié)議為revised BSD license(revised BSD license又稱為3-clause BSD License或者BSD 3-Clause License,一般使用BSD 3-Clause)
    image.png
  • OpenHamorny第三方開源軟件許可證類型必須是OSI明確定義的。
  • OSI明確定義的開源許可證有:https://opensource.org/licenses/alphabetical
  • BSD 3-Clause LicenseOSI明確定義的開源許可。

如下類型許可證可以引入到OpenHarmony項目中:

Apache License 2.0
Mulan Permissive Software License, Version 2
BSD 2-clause
BSD 3-clause
DOM4J License
PostgreSQL License
Eclipse Distribution License 1.0
MIT
ISC
ICU
University of Illinois/NCSA
W3C Software License
zlib/libpng
Academic Free License 3.0
Python Software Foundation License
Python Imaging Library Software License
Boost Software License Version 1.0
WTF Public License
UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
Zope Public License 2.0

如下類型許可證不建議引入到OpenHarmony項目中:

GNU GPL 1, 2, 3
GNU Affero GPL 3
GNU LGPL 2, 2.1, 3
QPL
Sleepycat License
Server Side Public License (SSPL) version 1
Code Project Open License (CPOL)
BSD-4-Clause/BSD-4-Clause (University of California-Specific)
Facebook BSD+Patents license
NPL 1.0/NPL 1.1
The Solipsistic Eclipse Public License
The "Don't Be A Dick" Public License
JSON License
Binary Code License (BCL)
Intel Simplified Software License
JSR-275 License
Microsoft Limited Public License
Amazon Software License (ASL)
Java SDK for Satori RTM license
Redis Source Available License (RSAL)
Booz Allen Public License
Creative Commons Non-Commercial
Sun Community Source License 3.0
Common Development and Distribution Licenses: CDDL 1.0 and CDDL 1.1
Common Public License: CPL 1.0
Eclipse Public License: EPL 1.0
IBM Public License: IPL 1.0
Mozilla Public Licenses: MPL 1.0, MPL 1.1, and MPL 2.0
Sun Public License: SPL 1.0
Open Software License 3.0
Erlang Public License
UnRAR License
SIL Open Font License
Ubuntu Font License Version 1.0
IPA Font License Agreement v1.0
Ruby License
Eclipse Public License 2.0: EPL 2.0

speexdsp的license以及版權(quán)內(nèi)容如下:

Copyright 2002-2008 	Xiph.org Foundation
Copyright 2002-2008 	Jean-Marc Valin
Copyright 2005-2007	Analog Devices Inc.
Copyright 2005-2008	Commonwealth Scientific and Industrial Research
                        Organisation (CSIRO)
Copyright 1993, 2002, 2006 David Rowe
Copyright 2003 		EpicGames
Copyright 1992-1994	Jutta Degener, Carsten Bormann

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

4.最新一次版本

  • 2022年6月16日,版本號1.2.1

5.代碼規(guī)模

linux系統(tǒng)提供了wc命令來統(tǒng)計文件的行數(shù),統(tǒng)計當前目錄下的所有文件行數(shù),終端輸入如下命令:

wc -l *
文件名 代碼行數(shù)
arch.h 232
bfin.h 15
buffer.c 176
fftwrap.c 448
fftwrap.h 58
filterbank.c 227
filterbank.h 66
fixed_arm4.h 135
fixed_arm5e.h 160
fixed_bfin.h 141
fixed_debug.h 497
fixed_generic.h 106
jitter.c 839
kiss_fft.c 523
_kiss_fft_guts.h 160
kiss_fft.h 108
kiss_fftr.c 297
kiss_fftr.h 51
math_approx.h 332
mdf.c 1279
misc_bfin.h 56
os_support.h 169
preprocess.c 1215
pseudofloat.h 379
resample.c 1239
resample_neon.h 339
resample_sse.h 128
scal.c 293
smallft.c 1261
smallft.h 46
vorbis_psy.h 97
speex_buffer.h 68
speexdsp_config_types.h 12
speexdsp_types.h 126
speex_echo.h 170
speex_jitter.h 197
speex_preprocess.h 219
speex_resampler.h 343
總行數(shù) 12207

功能分析

可以參考speexdsp提供的文檔分析功能
image.png

預(yù)處理器

預(yù)處理器被設(shè)計為在運行編碼器之前在音頻上使用。預(yù)處理器提供三個主要功能:

  • 噪聲抑制
  • 自動增益控制(AGC)
  • 語音活動檢測(V AD)

自適應(yīng)抖動緩沖區(qū)

  • 當通過UDP或RTP傳輸語音(或任何相關(guān)內(nèi)容)時,包可能會丟失,以不同的延遲到達,甚至亂序。
  • 抖動緩沖區(qū)的目的是重新排序數(shù)據(jù)包,并緩沖足夠長的時間,以便它們可以被發(fā)送以進行解碼。

聲學回聲消除器

回聲消除是為了提高遠端質(zhì)量。

  • 在任何免提通信系統(tǒng)中,遠端語音通過本地揚聲器播放。音頻在房間內(nèi)傳播,并被麥克風捕獲。如果從麥克風捕獲的音頻被直接發(fā)送到遠端,那么用戶就會聽到遠端語音的回聲。聲學回聲消除器設(shè)計用于在聲學回聲發(fā)送到遠端之前消除它。

image.png

重采樣器

這個重采樣器可以用于在任意兩個速率之間進行轉(zhuǎn)換(比率必須是有理數(shù)),并且可以控制質(zhì)量/復雜性的權(quán)衡。

  • 重采樣器在某些情況下將音頻從一個采樣率轉(zhuǎn)換到另一個采樣率。
  • 它可以用于混合具有不同采樣率的流、用于支持聲卡不支持的采樣率、用于轉(zhuǎn)碼等。

八、Speexdsp功能測試

測試邏輯

  • 在speexdsp原生庫的libspeexdsp目錄下有原生的測試源文件testresample.c、testresample2.c、testecho.c、testdenoise.c、testjitter.c。
    image.png
  • 進行功能測試需要對比pc端開發(fā)板的運行效果,因此需要在pc端編譯出測試用的可執(zhí)行文件(開發(fā)板上的已經(jīng)編譯出來了)。
    image.png

重采樣功能

  • 查看源碼可知,運行測試重采樣率的可執(zhí)行文件時,輸入一份音頻文件的同時需要指定處理后輸出的音頻文件。
  • 測試重采樣功能的源文件為testresample.c和testresample2.c。

testresample.c源碼分析如下:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

//要使用重采樣器,必須包含它的頭文件speex_resampler.h:
#include "speex/speex_resampler.h"
//基本輸入輸出函數(shù)的聲明
#include 
////頭文件中聲明了一些數(shù)學函數(shù)和宏
#include 

/*
stdlib.h中,包含了C語言的一些常用庫函數(shù)。
如動態(tài)內(nèi)存相關(guān)的malloc, realloc,zalloc,calloc,free等。
隨機數(shù)相關(guān)的rand,srand等。
系統(tǒng)相關(guān)的system, getenv,setenv等。
字符串轉(zhuǎn)數(shù)值函數(shù),atoi, atof,strtoul等。
如果在代碼中,調(diào)用了這個頭文件中的函數(shù)或者宏定義,則需引用該頭文件。
*/
#include 

//NN定義的是幀長度
#define NN 256

int main()
{
   spx_uint32_t i;
   short *in;
   short *out;
   float *fin, *fout;
   int count = 0;

//對于每一個被重采樣的流(流是一種抽象的概念,表示一連串的數(shù)據(jù)元素;流中的數(shù)據(jù)元素稱為幀F(xiàn)rame。),有必要創(chuàng)建一個重采樣狀態(tài):SpeexResamplerState *resampler;
//resampler = speex_resampler_init(nb_channels, input_rate, output_rate, quality, &err);
// nb_channels聲道數(shù)量,這段測試程序要求輸入的音頻聲道數(shù)量為1
// input_rate和output_rate指的是輸入音頻的采樣率和輸出音頻的采樣率。
// err錯誤碼
/*
    quality 是語音編解碼器方面的概念,范圍是0~10.通常,
   對于一般使用質(zhì)量為3是可以接受的,
   而對于專業(yè)音頻工作,質(zhì)量為10是最推薦的。
   質(zhì)量0通常具有良好的聲音(當然比使用線性插值重采樣更好),但可能會聽到偽影。 
*/
/*在數(shù)字音頻領(lǐng)域,常用的采樣率有:
        8000 Hz - 電話所用采樣率, 對于人的說話已經(jīng)足夠
        11025 Hz - 電話所用采樣率
        22050 Hz - 無線電廣播所用采樣率
        32000 Hz - miniDV 數(shù)碼視頻 camcorder、DAT (LP mode)所用采樣率
        44100 Hz - 音頻 CD, 也常用于 MPEG-1 音頻(VCD,SVCD,MP3)所用采樣率
        47250 Hz - 商用 PCM 錄音機所用采樣率
        48000 Hz - miniDV、數(shù)字電視、DVD、DAT、電影和專業(yè)音頻所用的數(shù)字聲音所用采樣率
        50000 Hz - 商用數(shù)字錄音機所用采樣率
*/
   SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 10, NULL);

//96000是輸入音頻的采樣率,44100是輸出音頻的采樣率。單位為Hz
   speex_resampler_set_rate(st, 96000, 44100);

   speex_resampler_skip_zeros(st);

 /* 
   malloc函數(shù)的作用是讓系統(tǒng)尋找空閑地址后為你分配一塊指定大小的空間來給你使用,
   這一塊空間其實要比你申請的空間大一些,它包含兩個部分:1.你申請的空間;2.記錄這個空間信息的空間。
*/
   in = malloc(NN*sizeof(short));
   out = malloc(2*NN*sizeof(short));
   fin = malloc(NN*sizeof(float));
   fout = malloc(2*NN*sizeof(float));

//while(1):這是一個死循環(huán),一直在while里循環(huán).
//調(diào)試代碼時,為了檢測一部分代碼是否OK,可加測試點while(1),測試這段代碼。
   while (1)
   {
      spx_uint32_t in_len;
      spx_uint32_t out_len;
/*從終端獲取音頻數(shù)據(jù)*/
      fread(in, sizeof(short), NN, stdin);

//feof()是檢測流上的文件結(jié)束符的函數(shù),如果文件結(jié)束,則返回非0值,否則返回0
      if (feof(stdin))
         break;
      for (i=0;i2*NN;
      /*if (count==2)
         speex_resampler_set_quality(st, 10);*/

//實際的重采樣是使用speex_resampler_process_int(resampler, channelID, in, &in_length, out, &out_length);
//其中"channelID"是輸入的音頻的聲道。對于單聲道,使用0。也可以同時處理多個通道。
//其中"in"指針指向所選通道的輸入緩沖區(qū)的第一個樣本,輸出指向輸出的第一個樣本。
//in_length和out_length分別指定輸入和輸出緩沖區(qū)的大小。
      speex_resampler_process_float(st, 0, fin, &in_len, fout, &out_len);
      for (i=0;ifloor(.5+fout[i]);
      /*speex_warning_int("writing", out_len);*/

/*轉(zhuǎn)換后的數(shù)據(jù)輸入到終端顯示*/
      fwrite(out, sizeof(short), out_len, stdout);
      count++;
   }
   speex_resampler_destroy(st);

//free函數(shù)接受一個指針,然后將指針指向的地址還給系統(tǒng)。(但它不會改變指針的指向,所以一般在free之后還要將指針置
   空,不然你的這個指針就會變成野指針)
//一般來說,malloc函數(shù)應(yīng)該和free函數(shù)成對出現(xiàn),防止向系統(tǒng)要的內(nèi)存太多系統(tǒng)不高興。
   free(in);
   free(out);
   free(fin);
   free(fout);
   return 0;
}
;i++)>;i++)>

可以得知:

  • 輸入音頻的采樣率要求為96000Hz、聲道為單聲道。
  • 輸出音頻的采樣率為44100。

回聲消除功能

  • 運行測試回聲消除的可執(zhí)行文件時,需要輸入兩段音頻文件,分別為一份麥克風的音頻、一份speaker的音頻。另外需要指定一份處理后輸出的音頻文件。采樣率都為8000Hz
  • 測試回聲消除功能的源文件為testecho.c。
    testecho.c源碼分析如下:
/* 
Speex 源碼中附帶的這個例子,只適合于串行的鏈式媒體流,當媒體播放、媒體采集、媒體網(wǎng)
絡(luò)數(shù)據(jù)接口分屬在不同現(xiàn)成時,就會存在同步問題,異步線程會導致信號延遲加大,回聲消除收斂效果不好。
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/*使用回聲消除器需要加#include "speex/speex_echo.h"*/
#include "speex/speex_echo.h"
/*使用預(yù)處理器需要添加#include "speex/speex_preprocess.h"*/
#include "speex/speex_preprocess.h"
#include 
//stdlib 頭文件即standard library標準庫頭文件 
#include 
// sys/types.h中文名稱為基本系統(tǒng) 數(shù)據(jù)類型。在應(yīng)用程序源文件中包含  以訪問 _LP64 和 _ILP32 的定義
#include  
//stat.h頭文件,輕松獲取文件屬性
#include  
//fcntl.h相關(guān)函數(shù) open,fcntl,shutdown,unlink,fclose
#include  

//NN是frame_size幀長度,TAIL是filter_length濾波器長度
#define NN 128
#define TAIL 1024 

//當你需要程序帶參數(shù)地啟動的時候,就用int main(int argc, char *argv[])
int main(int argc, char **argv) 
{
//FILE* 指針作為文件句柄,是文件訪問的唯一標識,它由fopen函數(shù)創(chuàng)建,fopen打開文件成功,則返回一個有效的FILE*指針,否則返回空指針NULL //[n?l]
   FILE *echo_fd, *ref_fd, *e_fd;
   short echo_buf[NN], ref_buf[NN], e_buf[NN];
   SpeexEchoState *st;
   SpeexPreprocessState *den;
//采樣率為8000.單位為hz
   int sampleRate = 8000;

   if (argc != 4)
   {
      fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.swn");
      exit(1);
   }

// fopen函數(shù)用于打開文件
   echo_fd = fopen(argv[2], "rb");
   ref_fd  = fopen(argv[1],  "rb");
   e_fd    = fopen(argv[3], "wb");

/*
1.創(chuàng)建一個回聲消除狀態(tài):SpeexEchoState *echo_state = speex_echo_state_init(frame_size, filter_length);
前邊的語句SpeexEchoState *st;  
2.NN是frame_size幀長度,TAIL是filter_length濾波器長度
*/·
   st = speex_echo_state_init(NN, TAIL);
   den = speex_preprocess_state_init(NN, sampleRate);
   speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate);
/*
如果你想進一步減少信號中的回波,你可以通過將回波消除器與預(yù)處理器相關(guān)聯(lián)來實現(xiàn).這是通過調(diào)用:
speex_preprocess_ctl(preprocess_state, SPEEX_PREPROCESS_SET_ECHO_STATE,echo_state);
*/
   speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st);
   while (!feof(ref_fd) && !feof(echo_fd))
   {
      fread(ref_buf, sizeof(short), NN, ref_fd);
      fread(echo_buf, sizeof(short), NN, echo_fd);
/*創(chuàng)建回聲消除器狀態(tài)后,可以通過以下方式處理音頻: 
speex_echo_cancellation(echo_state, input_frame, echo_frame, output_frame); 
其中,input_frame是麥克風捕捉到的音頻,echo_frame是揚聲器播放的信號(需要去除),output_frame是去除回聲的信號。
*/
      speex_echo_cancellation(st, ref_buf, echo_buf, e_buf);
      speex_preprocess_run(den, e_buf);
      fwrite(e_buf, sizeof(short), NN, e_fd);
   }
   speex_echo_state_destroy(st); 
//可以用以下方法消除回聲抵消狀態(tài):speex_echo_state_destroy(echo_state);
   speex_preprocess_state_destroy(den);
// fclose(FILE *fp) 一般地,fclose(fp)應(yīng)與fopen配對使用,特別是含有寫方式的文件,若不關(guān)閉,可能會造成文件數(shù)據(jù)丟失。
   fclose(e_fd);
   fclose(echo_fd);
   fclose(ref_fd);
   return 0;
}

預(yù)處理功能

  • 運行測試預(yù)處理功能的可執(zhí)行文件時,輸入一份音頻文件的同時需要指定處理后輸出的音頻文件。(采樣率為8000Hz)
  • 測試源文件testdenoise.c測試的是預(yù)處理功能中的噪聲抑制。

testdenoise.c源碼分析如下:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
//使用預(yù)處理功能先#include "speex/speex_preprocess.h"
#include "speex/speex_preprocess.h"
#include 
//定義NN為160
#define NN 160

int main()
{
   short in[NN];
   int i;
/*
然后,可以創(chuàng)建一個預(yù)處理器狀態(tài):SpeexPreprocessState *preprocess_state = speex_preprocess_state_init(frame_size,sampling_rate);
preprocess_state(預(yù)處理狀態(tài))
frame_size指的是幀長度
sampling_rate指的是采樣率
*/
   SpeexPreprocessState *st;
   int count=0;
   float f;

/*frame_size(幀長度)為160,采樣率為8000*/
   st = speex_preprocess_state_init(NN, 8000);

/*預(yù)處理器的行為可以通過以下方式改變:speex_preprocess_ctl(preprocess_state, request, ptr);*/

/*SPEEX_PREPROCESS_SET_DENOISE Turns denoising on(1) or off(2) (spx_int32_t)*/
   i=1; // i=1就是打開預(yù)處理器的降噪功能;i=2就是關(guān)閉降噪功能
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i); 

/*SPEEX_PREPROCESS_SET_AGC Turns automatic gain control (AGC) on(1) or off(2) (spx_int32_t)*/
/*AGC全稱是自動增益控制,作用是針對不同的強度的信號使用不同的增益進行放大,使得信號最終的輸出幅度維持在同一標準*/
   i=0; // 
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i);

   i=8000;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);

/*SPEEX_PREPROCESS_SET_DEREVERB Turns reverberation removal on(1) or off(2) (spx_int32_t)*/
//reverberation removal混響消除
   i=0;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i);

   f=.0;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);

   f=.0;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);

/* while(1):這是一個死循環(huán),一直在while里循環(huán),調(diào)試代碼時,為了檢測一部分代碼是否OK,可加測試點while(1),測試這段代碼*/
   while (1)
   {
      int vad;
      /*C 庫函數(shù) size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 從給定流 stream 讀取數(shù)據(jù)到 ptr 所指向的數(shù)組中。*/
      fread(in, sizeof(short), NN, stdin);
/*
feof()是檢測流上的文件結(jié)束符的函數(shù),如果文件結(jié)束,則返回非0值,否則返回0
一般在文件操作,中經(jīng)常使用feof()判斷文件是否結(jié)束。
*/
      if (feof(stdin))
         break;
/*
對于每個輸入幀,需要調(diào)用:speex_preprocess_run(preprocess_state, audio_frame);
其中audio_frame被用作輸入和輸出。
*/
//fwrite和fread是以記錄為單位的I/O函數(shù),fread和fwrite函數(shù)一般用于二進制文件的輸入輸出。
      vad = speex_preprocess_run(st, in);
      /*fprintf (stderr, "%dn", vad);*/
      fwrite(in, sizeof(short), NN, stdout);
      count++;
   }
//預(yù)處理器狀態(tài)可以通過以下方式銷毀:speex_preprocess_state_destroy(preprocess_state);
   speex_preprocess_state_destroy(st);
   return 0;
}

抖動緩沖功能

當通過UDP或RTP傳輸語音(或任何相關(guān)內(nèi)容)時,包可能會丟失,以不同的延遲到達,甚至亂序。

1.抖動緩沖區(qū)的目的是重新排序數(shù)據(jù)包,并緩沖足夠長的時間,以便它們可以被發(fā)送以進行解碼。

2.測試源文件testjitter.c,這個去抖動測試需要接收來自udp/rtp的網(wǎng)絡(luò)語音數(shù)據(jù),原生測試程序沒有做到真正意義上的測試,從程序上看是告訴用戶如何使用接口。

testjitter.c源碼分析:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/*jitter buffer可以通過以下方式啟用:#include */
#include "speex/speex_jitter.h"
#include 

union jbpdata {  
/*
聯(lián)合類型的聲明,union是聯(lián)合體關(guān)鍵字;聯(lián)合是一種特殊的自定義類型,該種類型定義的變量也包含一系列的成員,特征是這些成員共用同一塊空間,所以聯(lián)合體也被稱為共用體。
抖動緩沖器是一個共享的數(shù)據(jù)區(qū)域
*/
  unsigned int idx; 
//unsigned int是整數(shù)類型 ,存儲大小為2 或 4 字節(jié),值范圍為0 到 65,535 或 0 到 4,294,967,295
//unsigned char的表示范圍為0~255 此處定義了一個擁有四個元素的數(shù)組
  unsigned char data[4];
};

void synthIn(JitterBufferPacket *in, int idx, int span) {
  union jbpdata d;
  d.idx = idx;

  in->data = d.data;
  in->len = sizeof(d);
  in->timestamp = idx * 10;
  in->span = span * 10;
  in->sequence = idx;
  in->user_data = 0;
}

void jitterFill(JitterBuffer *jb) {
   char buffer[65536];
   JitterBufferPacket in, out;
   int i;

   out.data = buffer;

   jitter_buffer_reset(jb);

   for(i=0;i<100;++i) {
     synthIn(&in, i, 1);
     jitter_buffer_put(jb, &in);

     out.len = 65536;

     /*
     當解碼器準備解碼數(shù)據(jù)包時,需要解碼的數(shù)據(jù)包可以通過以下方式獲得:
     int start_offset;
     err = jitter_buffer_get(state, &packet, desired_span, &start_offset);
     */
    //如果從不同的線程調(diào)用jitter_buffer_put()和jitter_buffer_get(),那么需要使用互斥鎖來保護jitter緩沖區(qū)狀態(tài)。
     if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) {
       printf("Fill test failed iteration %dn", i);
     }
     if (out.timestamp != i * 10) {
       printf("Fill test expected %d got %dn", i*10, out.timestamp);
     }
/*因為jitter緩沖區(qū)被設(shè)計為不使用顯式計時器,所以需要顯式地告訴它時間。這是通過調(diào)用:jitter_buffer_tick(state);
*/
     jitter_buffer_tick(jb);
   }
}

/*
當一個包到達時,它需要通過以下方式插入到j(luò)itter buffer中:
JitterBufferPacket packet;
jitter_buffer_put(state, &packet);
*/
int main()
{
   char buffer[65536];
   JitterBufferPacket in, out;
   int i;

   /* 新的抖動緩沖狀態(tài)可以通過以下方式初始化:JitterBuffer *state = jitter_buffer_init(step);
   step參數(shù)是用于調(diào)整延遲的默認時間步長還有做隱藏,step參數(shù)的值總是為1,也可以是更高的值。
   */

   JitterBuffer *jb = jitter_buffer_init(10);

   out.data = buffer;

   /* Frozen sender case */
   jitterFill(jb);
   for(i=0;i<100;++i) {
     out.len = 65536;
     jitter_buffer_get(jb, &out, 10, NULL);
     jitter_buffer_tick(jb);
   }
   synthIn(&in, 100, 1);
   jitter_buffer_put(jb, &in);
   out.len = 65536;
   if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) {
     printf("Failed frozen sender resynchronizen");
   } else {
     printf("Frozen sender: Jitter %dn", out.timestamp - 100*10);
   }
   return 0;
}

測試步驟

編譯pc端上的測試用的可執(zhí)行程序

image.png
編譯pc端的可執(zhí)行程序:

gcc testdenoise.c -L /home/jiajiahao/Desktop/speexdsp-SpeexDSP-1.2.1/build/lib -o testdenoise -I /home/jiajiahao/Desktop/speexdsp-SpeexDSP-1.2.1/include -lm -lspeexdsp

image.png
其中:

  • gcc后面是測試用的源文件
  • -L 后指定so庫所在的文件夾
  • -l+so庫的名字(除去lib和后綴)
  • -o 后面是可執(zhí)行文件的名字,
  • -l 后面是測試用的源文件要用到的頭文件的路徑

將編譯生成的庫以及測試用的可執(zhí)行文件推送到開發(fā)板上

  • hdc工具的使用 請參考用hdc工具在OpenHarmony3.2 上安裝應(yīng)用中的相關(guān)內(nèi)容
  • 獲取了ohos源碼,也可以執(zhí)行./build.sh --product-name ohos-sdk編譯sdk。
    • 如果有這樣的編譯報錯,說明依賴的庫沒在linux上安裝完整。
      image.png
    • 安轉(zhuǎn)完整才能成功編譯。
sudo apt-get update 
sudo apt-get install binutils binutils-dev git git- lfs gnupg flex bison gperf build-essential zip 
curl zlib1g-dev gcc-multilib g+±m(xù)ultilib gcc-arm-linux-gnueabi libc6-dev-i386 libc6-dev-amd64 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils 
xsltproc unzip m4 bc gnutls-bin python3.8 python3-pip ruby genext2fs device-tree-compiler make 
libffi-dev e2fsprogs pkg-config perl openssl libssl-dev libelf-dev libdwarf-dev u-boot-tools mtd-
utils cpio doxygen liblz4-tool openjdk-8-jre gcc g++ texinfo dosfstools mtools default-jre default-
jdk libncurses5 apt-utils wget scons python3.8-distutils tar rsync git-core libxml2-dev lib32z-dev 
grsync xxd libglib2.0-dev libpixman-1-dev kmod jfsutils reiserfsprogs xfsprogs squashfs-tools 
pcmciautils quota ppp libtinfo-dev libtinfo5 libncurses5-dev libncursesw5 libstdc++6 gcc-arm-none-
eabi vim ssh locales

1.通過與ohos版本匹配的hdc_std工具,將編譯生成的庫以及測試用的可執(zhí)行文件推送到開發(fā)板上

hdc_std shell               
mount -o remount,rw /	    ## 重新加載系統(tǒng)為可讀寫
mkdir speexdsp              ## 創(chuàng)建speexdsp目錄存放測試用例
exit                        ## 退出開發(fā)板系統(tǒng)

2.將壓縮包push到開發(fā)板

hdc_std file send speexdsp.tar /speexdsp

3.解壓壓縮包并將庫文件拷貝到對應(yīng)的目錄

本次移植是基于openharmony標準系統(tǒng)3.2Beta1版本,是arm64位系統(tǒng)

hdc_std shell              ## 進入開發(fā)板系統(tǒng)
cd speexdsp
tar -xvf speexdsp.tar
cp libspeexdsp_share.z.so /system/lib64/ ## 將庫文件拷貝系統(tǒng)目錄

執(zhí)行測試程序、分析測試結(jié)果

分析測試結(jié)果需要使用到的音頻處理軟件是ocenaudio,下載地址:https://www.ocenaudio.com/en/
image.png

①執(zhí)行testresample可執(zhí)行文件
通過分析testresample.c源碼可知:執(zhí)行測試程序時輸入一份采樣率為96000Hz并且為單聲道的音頻時,經(jīng)過重采樣輸出的音頻采樣率為44100Hz。
在pc端運行
輸入的音頻為input.pcm,把它拷貝到testresample同目錄下,并且新建空白文檔命名為output.pcm。
image.png
打開終端執(zhí)行如下命令:

chmod 777 testresample
./testresample < input.pcm > output.pcm

使用重定向<符號指定輸入文件、>符號指定輸出文件
image.png

輸出的output.pcm采樣率變?yōu)?4100Hz,音頻的波形圖聲譜圖如下:

image.png

在rk3568上運行

這里測試testresample時,將一份與pc端同樣的input.pcm和output.pcm拷貝至開發(fā)板speexdsp目錄。
在開發(fā)板speexdsp目錄執(zhí)行語句如下

chmod 777 testresample                  ## 添加可執(zhí)行權(quán)限
./testresample < input.pcm > output.pcm

image.png

將開發(fā)板輸出的output.pcm拷貝至pc端

hdc_std file recv /speexdsp/output.pcm C:UsersjjhDesktop

image.png

測試結(jié)果:經(jīng)過重采樣,pc端和rk3568開發(fā)板輸出的output.pcm音頻采樣率都為44100Hz,兩者運行測試程序testresample結(jié)果一致。

②執(zhí)行testresample2可執(zhí)行文件

通過分析testresample2.c源碼可知,執(zhí)行測試程序時需要指定一份空白的單聲道音頻文件output.pcm。

測試testresample2時,需要把空白的單聲道音頻文件output.pcm拷貝至開發(fā)板speexdsp目錄。
pc端運行
執(zhí)行語句如下:

./testresample2 > output.pcm

輸出結(jié)果如下:
終端打印信息
image.png

輸出音頻output.pcm波形圖和聲譜圖如下:
image.png

rk3568開發(fā)板上運行
執(zhí)行語句如下:

./testresample2 > output.pcm

image.png

測試結(jié)果:輸出一份不為空的output.pcm音頻文件,并且在終端輸出文本如下:

1000 0 1024 22 -> 1024 0                  
1100 0 1024 24 -> 1024 15
1200 0 1024 26 -> 926 26
1300 926 1122 31 -> 1048 31
1400 950 1098 33 -> 1032 33
...
...
...
127600 1024 1024 2723 -> 1024 2723
...
...
127900 1024 1024 2729 -> 1024 2729
128000 1024 1024 2731 -> 1024 2730

以最后一行"128000 1024 1024 2731 -> 1024 2730“”為例,其中128000為采樣率(Hz);1024為一個編碼單元采樣點數(shù)(幀);1024為輸入音頻理論幀長;2731為輸出音頻理論幀長。"->"符號后的1024為經(jīng)過重采樣處理輸入音頻實際幀長,2730為輸出音頻實際幀長。

  • pc端和rk3568開發(fā)板運行testresample2可執(zhí)行程序效果一致。

③執(zhí)行testecho可執(zhí)行文件

測試testecho時,需要輸入兩份音頻文件,同時需要指定一份輸出的音頻文件。

輸入的兩份音頻一份為speaker.wav(麥克風收錄的說話人語音信號+在房間多徑反射的語音),另一份為micin.wav(麥克風收錄的房間多徑反射的語音)。

  • speaker.wav正常房間環(huán)境下收錄說話人說話聲音即可,mic2.pcm在正常環(huán)境收錄時說話人不說話即可。
  • 同時需要指定一份testecho_output.wav輸出文件。

執(zhí)行語句如下:

./testecho speaker.wav micin.wav testecho_output.wav

image.png

測試結(jié)果:對比輸入的speaker.wav和輸出testecho_output.wav的波形圖和聲譜圖,回聲已經(jīng)被消除。pc端和rk3568開發(fā)板運行testecho可執(zhí)行程序效果一致。

image.png

④執(zhí)行testdenoise可執(zhí)行文件

通過分析testdenoise.c源碼,執(zhí)行測試程序時需要指定一份輸入的不為空的8000Hz的input.pcm音頻,并且需要指定一份空的輸出的output.pcm音頻。

rk3568上運行
執(zhí)行語句如下:

./testdenoise < input.pcm > output.pcm

image.png

測試結(jié)果:對比輸入的input.pcm和輸出的outpu.pcm的波形圖和聲譜圖,噪聲已經(jīng)被消除。pc端和rk3568開發(fā)板運行testdenoise可執(zhí)行程序效果一致。

image.png

⑤執(zhí)行testjitter可執(zhí)行文件

通過分析testjitter.c源碼,測試需要接收來自udp/rtp的網(wǎng)絡(luò)語音數(shù)據(jù),原生測試程序沒有做到真正意義上的測試,從程序上看是告訴用戶如何使用接口。

執(zhí)行語句如下

./testjitter

測試結(jié)果:終端打印出語句

Frozen sender: Jitter 0

pc端和rk3568開發(fā)板運行testjitter可執(zhí)行程序效果一致。
image.png

下期預(yù)告:OAT開源掃描和三方庫上倉基本要求

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • dayu200
    +關(guān)注

    關(guān)注

    1

    文章

    26

    瀏覽量

    1156
  • 潤和軟件
    +關(guān)注

    關(guān)注

    1

    文章

    239

    瀏覽量

    801
收藏 人收藏

    評論

    相關(guān)推薦

    瑞芯微RK3566鴻蒙開發(fā)板OpenHarmony標準系統(tǒng)應(yīng)用兼容性測試指導

    本文OpenHarmony標準系統(tǒng)應(yīng)用兼容性測試指導,適用鴻蒙系統(tǒng)軟件開發(fā)測試的新手入門學習課程,設(shè)備為觸覺智能的瑞芯微RK3566開發(fā)板,型號Purple Pi OH。是Laval官
    的頭像 發(fā)表于 09-10 11:56 ?123次閱讀
    瑞芯微RK3566鴻蒙<b class='flag-5'>開發(fā)板</b><b class='flag-5'>OpenHarmony</b><b class='flag-5'>標準系統(tǒng)</b>應(yīng)用兼容性測試指導

    開鴻“龍芯+OpenHarmony開發(fā)平臺DAYU431先鋒派新品發(fā)布

    開鴻基于全新龍芯2K0300芯片平臺的重磅新品開鴻HH-SCDAYU431先鋒派開發(fā)平臺正式上市,成為開鴻DAYU系列產(chǎn)品中符合
    的頭像 發(fā)表于 08-07 14:50 ?261次閱讀
    <b class='flag-5'>潤</b>開鴻“龍芯+<b class='flag-5'>OpenHarmony</b>”<b class='flag-5'>開發(fā)</b>平臺<b class='flag-5'>DAYU</b>431先鋒派新品發(fā)布

    鴻蒙OpenHarmony【基于Hi3516DV300開發(fā)板(時鐘應(yīng)用開發(fā))】

    如何快速搭建基于OpenHarmony標準系統(tǒng)(Hi3516DV300開發(fā)板)的應(yīng)用開發(fā)環(huán)境,并基于一個時鐘APP示例逐步展示應(yīng)用的創(chuàng)建、開發(fā)
    的頭像 發(fā)表于 05-08 15:27 ?946次閱讀
    鴻蒙<b class='flag-5'>OpenHarmony</b>【基于Hi3516DV300<b class='flag-5'>開發(fā)板</b>(時鐘應(yīng)用<b class='flag-5'>開發(fā)</b>)】

    鴻蒙OpenHarmony南向:【Hi3516標準系統(tǒng)入門(命令行方式)】

    除小型系統(tǒng)外,Hi3516DV300開發(fā)板還支持標準系統(tǒng)。此章節(jié)簡要介紹如何使用命令行在Hi3516DV300開發(fā)板上進行標準系統(tǒng)
    的頭像 發(fā)表于 05-08 09:26 ?685次閱讀
    鴻蒙<b class='flag-5'>OpenHarmony</b>南向:【Hi3516<b class='flag-5'>標準系統(tǒng)</b>入門(命令行方式)】

    鴻蒙OpenHarmony標準系統(tǒng) 運行】(基于RK3568開發(fā)板

    燒錄完成重啟開發(fā)板后,系統(tǒng)將會自動啟動。開發(fā)板附帶的屏幕呈現(xiàn)以下界面,表明系統(tǒng)已運行成功。
    的頭像 發(fā)表于 05-06 15:38 ?367次閱讀
    鴻蒙<b class='flag-5'>OpenHarmony</b>【<b class='flag-5'>標準系統(tǒng)</b> 運行】(基于RK3568<b class='flag-5'>開發(fā)板</b>)

    OpenHarmony開發(fā)實例:【 待辦事項TodoList】

    TodoList應(yīng)用是基于OpenHarmony SDK開發(fā)的安裝在和HiSpark Taurus AI Camera(Hi3516d)開發(fā)板標準
    的頭像 發(fā)表于 04-22 22:00 ?577次閱讀
    <b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發(fā)</b>實例:【 待辦事項TodoList】

    【鴻蒙】標準系統(tǒng)移植指南

    標準系統(tǒng)移植指南 本文描述了移植一塊開發(fā)板的通用步驟,和具體芯片相關(guān)的詳細移植過程無法在此一一列舉。后續(xù)社區(qū)還會陸續(xù)發(fā)布
    的頭像 發(fā)表于 02-27 14:36 ?665次閱讀
    【鴻蒙】<b class='flag-5'>標準系統(tǒng)</b><b class='flag-5'>移植</b>指南

    請問DAYU200有SPI可以用么

    大家好,請問DAYU200有SPI可以用么 我看這里https://developer.huawei.com/consumer/cn/market/prod-detail?productId
    發(fā)表于 02-20 11:38

    開鴻基于高性能RISC-V開源架構(gòu)DAYU800通過OpenHarmony兼容性測評

    近期,江蘇開鴻數(shù)字科技有限公司(以下簡稱“開鴻”)基于高性能RISC-V開源架構(gòu)處理器研發(fā)的OpenHarmony標準系統(tǒng)開發(fā)平臺HH-SCDAYU800通過
    發(fā)表于 12-14 17:33

    rk3568 dayu200開發(fā)版故障

    dayu200開發(fā)版卡在 DAYU開機界面,但是通過截屏軟件可以顯示正確圖像。
    發(fā)表于 11-30 09:53

    OpenHarmony開發(fā)板匯總

    Tiger(A311D)標準系統(tǒng)DAYU200開發(fā)套件(RK3568)標準系統(tǒng):軟通揚帆富設(shè)備開發(fā)板(RK3399)
    發(fā)表于 10-19 11:27

    標準系統(tǒng)DAYU110(SL8541E)

    開發(fā)板名稱(芯片型號) 大禹系列DAYU110(SL8541E) 芯片架構(gòu) ARM CortexA53 CPU頻率 1.4GHZ 介紹(字數(shù)請控制在200字以內(nèi)) 和大禹系列
    發(fā)表于 10-19 10:56

    標準系統(tǒng)DAYU200開發(fā)套件(RK3568)

    高效能NPU,支持藍牙、Wi-Fi、音頻、視頻和攝像頭等功能,擁有豐富的擴展接口,支持多種視頻輸入輸出接口,是社區(qū)首款合入OpenHarmony主線的標準系統(tǒng)開發(fā)平臺。 承接廠家(全稱) 和 技術(shù)聯(lián)系人
    發(fā)表于 10-19 10:42

    標準系統(tǒng):軟通揚帆富設(shè)備開發(fā)板(RK3399)

    級別 標準系統(tǒng) 開發(fā)板名稱(芯片型號) 軟通揚帆富設(shè)備開發(fā)板(RK3399) 芯片架構(gòu) 瑞芯微RK3399 CPU頻率 介紹(字數(shù)請控制在200字以內(nèi)) 采用瑞芯微 RK3399(雙
    發(fā)表于 10-19 10:37

    開鴻DAYU200DAYU210聯(lián)袂通過OpenHarmony 3.2 Release版本兼容性測評

    展示 關(guān)于開鴻HH-SCDAYU200開發(fā)平臺 基于瑞芯微RK3568芯片,支持OpenHarmony標準系統(tǒng),集成雙核心架構(gòu)GPU以及高
    發(fā)表于 09-22 11:11