mirror of https://github.com/drowe67/LPCNet.git
Merge branch 'master' into dr-mag
commit
55f1db3113
|
@ -0,0 +1,34 @@
|
|||
sudo: required
|
||||
language: generic
|
||||
dist: xenial
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
libc6-i386
|
||||
libspeexdsp-dev
|
||||
libsamplerate0-dev
|
||||
sox
|
||||
git
|
||||
|
||||
install:
|
||||
- export CODEC2DIR=${PWD}/codec2
|
||||
- export LPCNETDIR=${PWD}
|
||||
- export BUILDDIR=${PWD}/build_linux
|
||||
|
||||
script:
|
||||
# First build and install vanilla codec2 as we need -lcodec2 to build LPCNet
|
||||
- git clone https://github.com/drowe67/codec2.git
|
||||
- cd codec2
|
||||
- mkdir build_linux && cd build_linux && cmake .. && make VERBOSE=1 codec2
|
||||
# OK, build and test LPCNet
|
||||
- cd $LPCNETDIR && mkdir -p $BUILDDIR && cd $BUILDDIR
|
||||
- cmake -DCODEC2_BUILD_DIR=$CODEC2DIR/build_linux .. && make VERBOSE=1
|
||||
- cd src && sox ../../wav/wia.wav -t raw -r 16000 - | ./lpcnet_enc -s | ./lpcnet_dec -s > /dev/null
|
||||
# Re-build codec2 with LPCNet and test FreeDV 2020 support
|
||||
- cd $CODEC2DIR/build_linux
|
||||
- make clean
|
||||
- cmake -DLPCNET_BUILD_DIR=$BUILDDIR ..
|
||||
- make VERBOSE=1
|
||||
- cd src
|
||||
- ./freedv_tx 2020 $LPCNETDIR/wav/wia.wav - | ./freedv_rx 2020 - /dev/null
|
|
@ -5,28 +5,69 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
project(LPCNet C)
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wall -W -Wextra -Wno-unused-function -O3 -g -I. -MD ${CMAKE_C_FLAGS}")
|
||||
option(AVX2 "Enable AVX2 CPU optimizations." OFF)
|
||||
option(AVX "Enable AVX CPU optimizations." OFF)
|
||||
option(NEON "Enable NEON CPU optimizations for RPi." OFF)
|
||||
|
||||
execute_process(COMMAND grep -c "avx2" /proc/cpuinfo
|
||||
OUTPUT_VARIABLE AVX2)
|
||||
execute_process(COMMAND grep -c "avx " /proc/cpuinfo
|
||||
OUTPUT_VARIABLE AVX)
|
||||
execute_process(COMMAND grep -c "neon" /proc/cpuinfo
|
||||
OUTPUT_VARIABLE NEON)
|
||||
message("AVX2: ${AVX2} AVX: ${AVX} NEON: ${NEON}")
|
||||
include(GNUInstallDirs)
|
||||
mark_as_advanced(CLEAR
|
||||
CMAKE_INSTALL_BINDIR
|
||||
CMAKE_INSTALL_INCLUDEDIR
|
||||
CMAKE_INSTALL_LIBDIR
|
||||
)
|
||||
|
||||
if(${AVX2} GREATER 0)
|
||||
message(STATUS "avx2 processor flags found.")
|
||||
#
|
||||
# Prevent in-source builds
|
||||
# If an in-source build is attempted, you will still need to clean up a few
|
||||
# files manually.
|
||||
#
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
message(FATAL_ERROR "In-source builds in ${CMAKE_BINARY_DIR} are not "
|
||||
"allowed, please remove ./CMakeCache.txt and ./CMakeFiles/, create a "
|
||||
"separate build directory and run cmake from there.")
|
||||
endif("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
|
||||
# Set default flags
|
||||
set(CMAKE_C_FLAGS "-Wall -W -Wextra -Wno-unused-function -O3 -g -I. -MD ${CMAKE_C_FLAGS} -DENABLE_ASSERTIONS")
|
||||
|
||||
# Detection of available CPU optimizations
|
||||
if(UNIX AND NOT APPLE)
|
||||
message(STATUS "Looking for available CPU optimizations on Linux/BSD system...")
|
||||
execute_process(COMMAND grep -c "avx2" /proc/cpuinfo
|
||||
OUTPUT_VARIABLE AVX2)
|
||||
execute_process(COMMAND grep -c "avx " /proc/cpuinfo
|
||||
OUTPUT_VARIABLE AVX)
|
||||
execute_process(COMMAND grep -c "neon" /proc/cpuinfo
|
||||
OUTPUT_VARIABLE NEON)
|
||||
elseif(APPLE)
|
||||
# Under OSX we need to look through a few sysctl entries to determine what our CPU supports.
|
||||
message(STATUS "Looking for available CPU optimizations on an OSX system...")
|
||||
execute_process(COMMAND sysctl -a COMMAND grep machdep.cpu.leaf7_features COMMAND grep -c AVX2
|
||||
OUTPUT_VARIABLE AVX2)
|
||||
execute_process(COMMAND sysctl -a COMMAND grep machdep.cpu.features COMMAND grep -c AVX
|
||||
OUTPUT_VARIABLE AVX)
|
||||
elseif(WIN32)
|
||||
message(STATUS "No detection capability on Windows, assuming AVX is available.")
|
||||
set(AVX TRUE)
|
||||
else()
|
||||
message(STATUS "System is not *nix, processor specific optimizations cannot be determined.")
|
||||
message(" You can try setting them manually, e.g.: -DAVX2=1 or -DAVX=1 or -DNEON=1")
|
||||
endif()
|
||||
|
||||
if(${AVX2} OR ${AVX2} GREATER 0)
|
||||
message(STATUS "avx2 processor flags found or enabled.")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2 -mfma")
|
||||
elseif(${AVX} GREATER 0)
|
||||
elseif(${AVX} OR ${AVX} GREATER 0)
|
||||
# AVX2 machines will also match on AVX
|
||||
message(STATUS "avx processor flags found.")
|
||||
message(STATUS "avx processor flags found or enabled.")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx")
|
||||
endif()
|
||||
|
||||
# RPi
|
||||
if(${NEON} GREATER 0)
|
||||
message(STATUS "neon processor flags found.")
|
||||
if(${NEON} OR ${NEON} GREATER 0)
|
||||
message(STATUS "neon processor flags found or enabled.")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=armv8-a -mtune=cortex-a53")
|
||||
endif()
|
||||
|
||||
|
@ -57,5 +98,18 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
# Find codec2
|
||||
if(CODEC2_BUILD_DIR)
|
||||
find_package(codec2 REQUIRED
|
||||
PATHS ${CODEC2_BUILD_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
CONFIGS codec2.cmake
|
||||
)
|
||||
if(codec2_FOUND)
|
||||
message(STATUS "Codec2 library found in build tree.")
|
||||
endif()
|
||||
else()
|
||||
find_package(codec2 REQUIRED)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -18,19 +18,45 @@ set(lpcnet_freedv_srcs
|
|||
${lpcnet_SOURCE_DIR}/nnet_data.c
|
||||
)
|
||||
|
||||
add_library(lpcnetfreedv STATIC ${lpcnet_freedv_srcs})
|
||||
add_library(lpcnetfreedv SHARED ${lpcnet_freedv_srcs})
|
||||
target_link_libraries(lpcnetfreedv codec2)
|
||||
set_target_properties(lpcnetfreedv PROPERTIES
|
||||
PUBLIC_HEADER lpcnet_freedv.h
|
||||
)
|
||||
target_include_directories(lpcnetfreedv INTERFACE
|
||||
$<INSTALL_INTERFACE:include/lpcnet>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
)
|
||||
install(TARGETS lpcnetfreedv EXPORT lpcnet-config
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lpcnet
|
||||
)
|
||||
|
||||
install(EXPORT lpcnet-config
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lpcnet
|
||||
)
|
||||
# Export libfreedv target for import into codec2 from build tree.
|
||||
export(TARGETS lpcnetfreedv
|
||||
FILE ${CMAKE_BINARY_DIR}/lpcnetfreedv.cmake
|
||||
)
|
||||
|
||||
add_executable(dump_data dump_data.c)
|
||||
target_link_libraries(dump_data lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(test_lpcnet test_lpcnet.c)
|
||||
target_link_libraries(test_lpcnet lpcnetfreedv m)
|
||||
target_link_libraries(test_lpcnet lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(test_vec test_vec.c)
|
||||
target_link_libraries(test_vec m)
|
||||
if(AVX OR AVX2)
|
||||
add_executable(test_vec test_vec.c)
|
||||
target_link_libraries(test_vec m)
|
||||
else()
|
||||
message(WARNING "No AVX/AVX2 CPU flags identified, not building test_vec.")
|
||||
endif()
|
||||
|
||||
add_executable(quant_feat quant_feat.c)
|
||||
target_link_libraries(quant_feat lpcnetfreedv m)
|
||||
target_link_libraries(quant_feat lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(tcodec2_pitch tcodec2_pitch.c codec2_pitch.c)
|
||||
target_link_libraries(tcodec2_pitch m codec2)
|
||||
|
@ -42,7 +68,7 @@ add_executable(tdump tdump.c)
|
|||
target_link_libraries(tdump lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(quant_test quant_test.c)
|
||||
target_link_libraries(quant_test lpcnetfreedv m)
|
||||
target_link_libraries(quant_test lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(quant2c quant2c.c)
|
||||
target_link_libraries(quant2c m)
|
||||
|
@ -51,10 +77,10 @@ add_executable(diff32 diff32.c)
|
|||
target_link_libraries(diff32 m)
|
||||
|
||||
add_executable(quant_enc quant_enc.c)
|
||||
target_link_libraries(quant_enc lpcnetfreedv m)
|
||||
target_link_libraries(quant_enc lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(quant_dec quant_dec.c)
|
||||
target_link_libraries(quant_dec lpcnetfreedv m)
|
||||
target_link_libraries(quant_dec lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(lpcnet_enc lpcnet_enc.c)
|
||||
target_link_libraries(lpcnet_enc lpcnetfreedv m codec2)
|
||||
|
@ -63,4 +89,8 @@ add_executable(lpcnet_dec lpcnet_dec.c)
|
|||
target_link_libraries(lpcnet_dec lpcnetfreedv m codec2)
|
||||
|
||||
add_executable(idct idct.c)
|
||||
target_link_libraries(idct lpcnetfreedv m)
|
||||
target_link_libraries(idct lpcnetfreedv m codec2)
|
||||
|
||||
install(TARGETS lpcnet_enc lpcnet_dec
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
|
|
@ -56,8 +56,8 @@ static RNN_INLINE int lin2ulaw(float x)
|
|||
}
|
||||
|
||||
|
||||
/** RNNoise wrapper for malloc(). To do your own dynamic allocation, all you need t
|
||||
o do is replace this function and rnnoise_free */
|
||||
/** RNNoise wrapper for malloc(). To do your own dynamic allocation,
|
||||
all you need to do is replace this function and rnnoise_free */
|
||||
#ifndef OVERRIDE_RNNOISE_ALLOC
|
||||
static RNN_INLINE void *rnnoise_alloc (size_t size)
|
||||
{
|
||||
|
|
31
src/diff32.c
31
src/diff32.c
|
@ -1,3 +1,6 @@
|
|||
/* test tool to diffs two .f32 files */
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -5,23 +8,31 @@
|
|||
#define NB_FEATURES 55
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
float f1[NB_FEATURES],f2[NB_FEATURES],fdiff=0.0;
|
||||
int ret,f=0,i;
|
||||
float fdiff, fdiff_tot=0.0;
|
||||
int f=0;
|
||||
unsigned int ret, i, stride = NB_FEATURES;
|
||||
FILE *file1 = fopen(argv[1],"rb");
|
||||
assert(file1 != NULL);
|
||||
FILE *file2 = fopen(argv[2],"rb");
|
||||
while(fread(&f1,sizeof(float),NB_FEATURES,file1) == NB_FEATURES) {
|
||||
ret = fread(&f2,sizeof(float),NB_FEATURES,file2);
|
||||
if (ret != NB_FEATURES) break;
|
||||
for(i=0; i<NB_FEATURES; i++) {
|
||||
fdiff += fabs(f1[i]-f2[i]);
|
||||
|
||||
if (isnan(fdiff) || (fdiff > 1E-6)) {
|
||||
assert(file2 != NULL);
|
||||
if (argc == 4) {
|
||||
stride = atoi(argv[3]);
|
||||
}
|
||||
float f1[stride],f2[stride];
|
||||
while(fread(&f1,sizeof(float),stride,file1) == stride) {
|
||||
ret = fread(&f2,sizeof(float),stride,file2);
|
||||
if (ret != stride) break;
|
||||
for(i=0; i<stride; i++) {
|
||||
fdiff = fabs(f1[i]-f2[i]);
|
||||
fdiff_tot += fdiff;
|
||||
|
||||
if (isnan(fdiff) || (fdiff > 1E-3)) {
|
||||
printf("f: %d i: %d %f %f %f\n", f, i, f1[i], f2[i], fdiff);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
f++;
|
||||
}
|
||||
fprintf(stderr,"f: %d fdiff: %f\n", f, fdiff);
|
||||
fprintf(stderr,"stride: %d f: %d fdiff_tot: %f\n", stride, f, fdiff_tot);
|
||||
fclose(file1); fclose(file2);
|
||||
}
|
||||
|
|
|
@ -418,7 +418,7 @@ int main(int argc, char **argv) {
|
|||
if (strcmp(argv[dx], "-") == 0)
|
||||
f1 = stdin;
|
||||
else {
|
||||
f1 = fopen(argv[dx], "r");
|
||||
f1 = fopen(argv[dx], "rb");
|
||||
if (f1 == NULL) {
|
||||
fprintf(stderr,"Error opening input .s16 16kHz speech input file: %s\n", argv[dx]);
|
||||
exit(1);
|
||||
|
@ -427,14 +427,14 @@ int main(int argc, char **argv) {
|
|||
if (strcmp(argv[dx+1], "-") == 0)
|
||||
ffeat = stdout;
|
||||
else {
|
||||
ffeat = fopen(argv[dx+1], "w");
|
||||
ffeat = fopen(argv[dx+1], "wb");
|
||||
if (ffeat == NULL) {
|
||||
fprintf(stderr,"Error opening output feature file: %s\n", argv[dx+1]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (training) {
|
||||
fpcm = fopen(argv[dx+2], "w");
|
||||
fpcm = fopen(argv[dx+2], "wb");
|
||||
if (fpcm == NULL) {
|
||||
fprintf(stderr,"Error opening output PCM file: %s\n", argv[dx+2]);
|
||||
exit(1);
|
||||
|
@ -517,6 +517,11 @@ int main(int argc, char **argv) {
|
|||
c2_Sn[i+c2_Sn_size-c2_frame_size] = x[i];
|
||||
float f0, voicing, snr; int pitch_index;
|
||||
pitch_index = codec2_pitch_est(c2pitch, c2_Sn, &f0, &voicing, &snr);
|
||||
if (pitch_index >= 2*PITCH_MAX_PERIOD) pitch_index = 2*PITCH_MAX_PERIOD-1;
|
||||
if (pitch_index < 2*PITCH_MIN_PERIOD) pitch_index = 2*PITCH_MIN_PERIOD;
|
||||
assert(pitch_index < 2*PITCH_MAX_PERIOD);
|
||||
assert(pitch_index >= 2*PITCH_MIN_PERIOD);
|
||||
|
||||
features[2*NB_BANDS] = 0.01*(pitch_index-200);
|
||||
if (c2voicing_en) features[2*NB_BANDS+1] = voicing;
|
||||
//int pitch_index_lpcnet = 100*features[2*NB_BANDS] + 200;
|
||||
|
|
|
@ -28,8 +28,8 @@ float std[] = {
|
|||
int main(int argc, char *argv[]) {
|
||||
FILE *fin, *fout;
|
||||
fin = stdin; fout = stdout;
|
||||
uint ret;
|
||||
uint stride = NB_BANDS;
|
||||
unsigned int ret;
|
||||
unsigned int stride = NB_BANDS;
|
||||
int measure = 0;
|
||||
int scaling = 0;
|
||||
|
||||
|
@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
|
|||
float sum[NB_BANDS] = {0.0};
|
||||
float sumsq[NB_BANDS] = {0.0};
|
||||
float dctLy[stride], Ly[stride];
|
||||
uint i; for(i=0; i<stride; i++) Ly[stride] = 0.0;
|
||||
unsigned int i; for(i=0; i<stride; i++) Ly[stride] = 0.0;
|
||||
long n = 0;
|
||||
while(fread(dctLy, sizeof(float), stride, fin) == stride) {
|
||||
idct(Ly, dctLy);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
% linux_v_windows.m
|
||||
% David Rowe May 2019
|
||||
%
|
||||
% Part of system to generate and compare Linux and Windows test files
|
||||
% that contain LPCNet states. Use to track down issue with Windows version
|
||||
%
|
||||
% Run in Octave from LPCNet/src
|
||||
|
||||
1;
|
||||
|
||||
function [vec1 vec2] = check_vec(fig_num, name, vec1, vec2)
|
||||
# vector may be supplied as matrix that we need to reshape, e.g. for excitation signal
|
||||
[rows cols] = size(vec1);
|
||||
if cols != 1
|
||||
vec1 = reshape(vec1', 1, rows*cols);
|
||||
vec2= reshape(vec2', 1, rows*cols);
|
||||
end
|
||||
figure(fig_num); clf;
|
||||
plot(vec1); hold on; plot(vec2); hold off;
|
||||
title(name);
|
||||
diff = max(vec1-vec2);
|
||||
if diff < 1E-3
|
||||
printf("%s [PASS]\n", name);
|
||||
else
|
||||
printf("%s [FAIL]\n", name);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function check_matrix(fig_num, name, mat1, mat2)
|
||||
figure(fig_num); clf;
|
||||
[r c] = size(mat1);
|
||||
plotr=min(r,100);
|
||||
plotc=min(c,100);
|
||||
mesh(mat1(1:plotr,1:plotc)); hold on; mesh(mat2(1:plotr,1:plotc)); hold off;
|
||||
title(name);
|
||||
mdiff = mat1-mat2; diff = max(mdiff(:));
|
||||
if diff < 1E-3
|
||||
printf("%s [PASS]\n", name);
|
||||
else
|
||||
printf("%s [FAIL]\n", name);
|
||||
% find first row where problem occurs
|
||||
[rows cols]= size(mat1);
|
||||
first_error = 1; nerr = 0;
|
||||
for r=1:rows
|
||||
e = mat1(r,:) - mat2(r,:);
|
||||
if max(e) > 1E-3 && nerr < 3
|
||||
nerr++;
|
||||
[mx col] = max(e);
|
||||
printf("max error %f in row: %d col: %d\n", max(e), r, col);
|
||||
if (first_error)
|
||||
clf; plot(mat1(r,:),'g'); hold on; plot(mat2(r,:),'b'); plot(mat1(r,:) - mat2(r,:),'r'); hold off;
|
||||
first_error = 0;
|
||||
mat1(r,1:10)
|
||||
mat2(r,1:10)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
n_pitch_embed = 64;
|
||||
n_pitch = 1;
|
||||
n_pitch_gain = 1;
|
||||
n_lpc = 16;
|
||||
n_condition = 128;
|
||||
n_gru_a = 1152;
|
||||
n_last_sig = 160;
|
||||
n_pred = 160;
|
||||
n_exc = 160;
|
||||
n_pcm = 160;
|
||||
n_cols = n_pitch_embed + n_pitch + n_pitch_gain + n_lpc + n_condition + n_gru_a + n_last_sig + n_pred + n_exc + n_pcm;
|
||||
|
||||
linux=load_f32("../build_linux/src/test_lpcnet_statesq.f32", n_cols);
|
||||
[r c]=size(linux);
|
||||
printf("linux %d x %d\n", r, c);
|
||||
windows=load_f32("../build_win/src/test_lpcnet_statesq.f32", n_cols);
|
||||
[r c]=size(windows);
|
||||
printf("windows %d x %d\n", r, c);
|
||||
|
||||
fig = 1;
|
||||
st = 1;
|
||||
en = st + n_pitch_embed-1; check_matrix(fig++, "pitch_embed", linux(:,st:en), windows(:,st:en)); st += n_pitch_embed;
|
||||
check_vec(fig++, "pitch", linux(:,st), windows(:,st)); st += n_pitch;
|
||||
check_vec(fig++, "pitch_gain", linux(:,st), windows(:,st)); st += n_pitch_gain;
|
||||
en = st + n_lpc-1; check_matrix(fig++, "lpc", linux(:,st:en), windows(:,st:en)); st += n_lpc;
|
||||
en = st + n_condition-1; check_matrix(fig++, "condition", linux(:,st:en), windows(:,st:en)); st += n_condition;
|
||||
en = st + n_gru_a-1; check_matrix(fig++, "gru a", linux(:,st:en), windows(:,st:en)); st += n_gru_a;
|
||||
|
||||
en = st + n_last_sig-1; last_sig = check_vec(fig++, "last_sig", linux(:,st:en), windows(:,st:en)); st += n_last_sig;
|
||||
en = st + n_pred-1; pred = check_vec(fig++, "pred", linux(:,st:en), windows(:,st:en)); st += n_pred;
|
||||
en = st + n_exc-1; exc = check_vec(fig++, "exc", linux(:,st:en), windows(:,st:en)); st += n_exc;
|
||||
en = st + n_pcm-1; pcm = check_vec(fig++, "pcm", linux(:,st:en), windows(:,st:en)); st += n_pcm;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/bash
|
||||
# linux_v_windows.sh
|
||||
# David Rowe May 2019
|
||||
#
|
||||
# Part of system to generate and compare Linux and Windows test files
|
||||
# that contain LPCNet states. Use to track down issue with Windows version
|
||||
|
||||
export WINEPATH=$HOME/freedv-gui/codec2/build_win/src';'$HOME/freedv-gui/build_win/_CPack_Packages/win64/NSIS/FreeDV-1.4.0-devel-win64/bin/
|
||||
|
||||
w=all
|
||||
|
||||
# start in LPCNet dir
|
||||
p=$PWD
|
||||
|
||||
# Windows
|
||||
cd build_win/src && make tdump test_lpcnet lpcnet_enc lpcnet_dec
|
||||
wine lpcnet_enc.exe -s --infile ../../wav/$w.wav --outfile $w.bin
|
||||
wine lpcnet_dec.exe -s --infile $w.bin --outfile $w'q_out.raw'
|
||||
#wine tdump.exe ../../wav/$w.wav $w.f32
|
||||
#wine test_lpcnet.exe $w.f32 $w'_out.raw'
|
||||
cd $p
|
||||
|
||||
# Linux
|
||||
cd build_linux/src && make test_lpcnet lpcnet_enc lpcnet_dec diff32
|
||||
./lpcnet_dec -s --infile ../../build_win/src/$w.bin --outfile $w'q_out'.raw
|
||||
#./test_lpcnet ../../build_win/src/$w.f32 $w'_out.raw'
|
||||
./diff32 test_lpcnet_statesq.f32 ../../build_win/src/test_lpcnet_statesq.f32 1842
|
||||
cd $p
|
||||
|
||||
|
71
src/lpcnet.c
71
src/lpcnet.c
|
@ -54,6 +54,7 @@ struct LPCNetState {
|
|||
float old_gain[FEATURES_DELAY];
|
||||
int frame_count;
|
||||
float deemph_mem;
|
||||
FILE *ftest; /* used to dump states for automates tests */
|
||||
};
|
||||
|
||||
|
||||
|
@ -73,13 +74,14 @@ void run_frame_network(LPCNetState *lpcnet, float *condition, float *gru_a_condi
|
|||
float conv1_out[FEATURE_CONV1_OUT_SIZE];
|
||||
float conv2_out[FEATURE_CONV2_OUT_SIZE];
|
||||
float dense1_out[FEATURE_DENSE1_OUT_SIZE];
|
||||
|
||||
net = &lpcnet->nnet;
|
||||
RNN_COPY(in, features, NB_FEATURES);
|
||||
compute_embedding(&embed_pitch, &in[NB_FEATURES], pitch);
|
||||
celt_assert(FRAME_INPUT_SIZE == feature_conv1.nb_inputs);
|
||||
compute_conv1d(&feature_conv1, conv1_out, net->feature_conv1_state, in);
|
||||
if (lpcnet->frame_count < FEATURE_CONV1_DELAY) RNN_CLEAR(conv1_out, FEATURE_CONV1_OUT_SIZE);
|
||||
compute_conv1d(&feature_conv2, conv2_out, net->feature_conv2_state, conv1_out);
|
||||
celt_assert(FRAME_INPUT_SIZE == FEATURE_CONV2_OUT_SIZE);
|
||||
if (lpcnet->frame_count < FEATURES_DELAY) RNN_CLEAR(conv2_out, FEATURE_CONV2_OUT_SIZE);
|
||||
memmove(lpcnet->old_input[1], lpcnet->old_input[0], (FEATURES_DELAY-1)*FRAME_INPUT_SIZE*sizeof(in[0]));
|
||||
memcpy(lpcnet->old_input[0], in, FRAME_INPUT_SIZE*sizeof(in[0]));
|
||||
|
@ -87,6 +89,10 @@ void run_frame_network(LPCNetState *lpcnet, float *condition, float *gru_a_condi
|
|||
compute_dense(&feature_dense2, condition, dense1_out);
|
||||
compute_dense(&gru_a_dense_feature, gru_a_condition, condition);
|
||||
if (lpcnet->frame_count < 1000) lpcnet->frame_count++;
|
||||
|
||||
if (lpcnet->ftest) {
|
||||
fwrite(&in[NB_FEATURES], sizeof(float), EMBED_PITCH_OUT_SIZE, lpcnet->ftest);
|
||||
}
|
||||
}
|
||||
|
||||
void run_sample_network(NNetState *net, float *pdf, const float *condition, const float *gru_a_condition, int last_exc, int last_sig, int pred)
|
||||
|
@ -110,16 +116,27 @@ LPCNetState *lpcnet_create()
|
|||
LPCNetState *lpcnet;
|
||||
lpcnet = (LPCNetState *)calloc(sizeof(LPCNetState), 1);
|
||||
lpcnet->last_exc = 128;
|
||||
lpcnet->ftest = NULL;
|
||||
return lpcnet;
|
||||
}
|
||||
|
||||
void lpcnet_destroy(LPCNetState *lpcnet)
|
||||
{
|
||||
if (lpcnet->ftest) fclose(lpcnet->ftest);
|
||||
free(lpcnet);
|
||||
}
|
||||
|
||||
void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features, int N, int logmag)
|
||||
void lpcnet_open_test_file(LPCNetState *lpcnet, char file_name[]) {
|
||||
lpcnet->ftest = fopen(file_name, "wb");
|
||||
if (lpcnet->ftest == NULL) {
|
||||
fprintf(stderr, "Error opening LPCNet test file: %s\n", file_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features, int N)
|
||||
{
|
||||
static int count = 0;
|
||||
int i;
|
||||
float condition[FEATURE_DENSE2_OUT_SIZE];
|
||||
float lpc[LPC_ORDER];
|
||||
|
@ -128,7 +145,7 @@ void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features
|
|||
int pitch;
|
||||
float pitch_gain;
|
||||
/* FIXME: Remove this -- it's just a temporary hack to match the Python code. */
|
||||
static int start = LPC_ORDER+1;
|
||||
static int start = 0; /*(LPC_ORDER+1*/;
|
||||
/* FIXME: Do proper rounding once the Python code rounds properly. */
|
||||
pitch = (int)floor(.1 + 50*features[36]+100);
|
||||
pitch_gain = lpcnet->old_gain[FEATURES_DELAY-1];
|
||||
|
@ -137,16 +154,43 @@ void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features
|
|||
run_frame_network(lpcnet, condition, gru_a_condition, features, pitch);
|
||||
memcpy(lpc, lpcnet->old_lpc[FEATURES_DELAY-1], LPC_ORDER*sizeof(lpc[0]));
|
||||
memmove(lpcnet->old_lpc[1], lpcnet->old_lpc[0], (FEATURES_DELAY-1)*LPC_ORDER*sizeof(lpc[0]));
|
||||
|
||||
if (logmag) {
|
||||
float tmp[NB_BANDS];
|
||||
for (i=0;i<NB_BANDS;i++) tmp[i] = pow(10.f, features[i]);
|
||||
lpc_from_bands(lpcnet->old_lpc[0], tmp);
|
||||
float tmp[NB_BANDS];
|
||||
for (i=0;i<NB_BANDS;i++) tmp[i] = pow(10.f, features[i]);
|
||||
lpc_from_bands(lpcnet->old_lpc[0], tmp);
|
||||
}
|
||||
else
|
||||
lpc_from_cepstrum(lpcnet->old_lpc[0], features);
|
||||
lpc_from_cepstrum(lpcnet->old_lpc[0], features);
|
||||
|
||||
if (lpcnet->ftest) {
|
||||
float pitch_f = pitch;
|
||||
fwrite(&pitch_f, sizeof(float), 1, lpcnet->ftest);
|
||||
fwrite(&pitch_gain, sizeof(float), 1, lpcnet->ftest);
|
||||
fwrite(lpc, sizeof(float), LPC_ORDER, lpcnet->ftest);
|
||||
fwrite(condition, sizeof(float), FEATURE_DENSE2_OUT_SIZE, lpcnet->ftest);
|
||||
fwrite(gru_a_condition, sizeof(float), 3*GRU_A_STATE_SIZE, lpcnet->ftest);
|
||||
if (lpcnet->frame_count==1) {
|
||||
fprintf(stderr, "%d %d %d %d %d %d %d %d %d %d\n", EMBED_PITCH_OUT_SIZE, 1, 1, LPC_ORDER,FEATURE_DENSE2_OUT_SIZE,3*GRU_A_STATE_SIZE,N,N,N,N);
|
||||
fprintf(stderr, "ftest cols = %d\n", EMBED_PITCH_OUT_SIZE+1+1+LPC_ORDER+FEATURE_DENSE2_OUT_SIZE+3*GRU_A_STATE_SIZE+N+N+N+N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lpcnet->frame_count <= FEATURES_DELAY)
|
||||
{
|
||||
RNN_CLEAR(output, N);
|
||||
/* zero output when we return early on init */
|
||||
for(i=0; i<N; i++)
|
||||
output[i] = 0;
|
||||
/* pad test file when we return early */
|
||||
if (lpcnet->ftest) {
|
||||
float dummy[4]= {0.0};
|
||||
for(i=0; i<N; i++) {
|
||||
fwrite(dummy, sizeof(float), 4, lpcnet->ftest);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
for (i=start;i<N;i++)
|
||||
|
@ -171,11 +215,18 @@ void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features
|
|||
lpcnet->deemph_mem = pcm;
|
||||
if (pcm<-32767) pcm = -32767;
|
||||
if (pcm>32767) pcm = 32767;
|
||||
if (lpcnet->ftest) {
|
||||
float exc_f, last_sig_f;
|
||||
last_sig_f = ulaw2lin(last_sig_ulaw);
|
||||
fwrite(&last_sig_f, sizeof(float), 1, lpcnet->ftest);
|
||||
fwrite(&pred, sizeof(float), 1, lpcnet->ftest);
|
||||
exc_f = ulaw2lin(exc);
|
||||
fwrite(&exc_f, sizeof(float), 1, lpcnet->ftest);
|
||||
fwrite(&pcm, sizeof(float), 1, lpcnet->ftest);
|
||||
count++;
|
||||
}
|
||||
output[i] = (int)floor(.5 + pcm);
|
||||
}
|
||||
start = 0;
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,4 +41,6 @@ typedef struct LPCNetFreeDV LPCNetFreeDV;
|
|||
int lpcnet_bits_per_frame(LPCNetFreeDV *);
|
||||
int lpcnet_samples_per_frame(LPCNetFreeDV *);
|
||||
|
||||
void lpcnet_open_test_file(LPCNetState *lpcnet, char file_name[]);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -60,9 +60,14 @@ int main(int argc, char **argv) {
|
|||
int logmag = 0;
|
||||
int direct_split = 0;
|
||||
|
||||
fin = stdin;
|
||||
fout = stdout;
|
||||
|
||||
/* quantiser options */
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"infile", required_argument, 0, 'i'},
|
||||
{"outfile", required_argument, 0, 'u'},
|
||||
{"ber", required_argument, 0, 'b'},
|
||||
{"decimate", required_argument, 0, 'd'},
|
||||
{"numstages", required_argument, 0, 'n'},
|
||||
|
@ -76,8 +81,20 @@ int main(int argc, char **argv) {
|
|||
int c;
|
||||
int opt_index = 0;
|
||||
|
||||
while ((c = getopt_long (argc, argv, "b:d:n:o:p:sv", long_options, &opt_index)) != -1) {
|
||||
while ((c = getopt_long (argc, argv, "b:d:n:o:p:svi:u:", long_options, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
if ((fin = fopen(optarg, "rb")) == NULL) {
|
||||
fprintf(stderr, "Couldn't open input file: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if ((fout = fopen(optarg, "wb")) == NULL) {
|
||||
fprintf(stderr, "Couldn't open output file: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
ber = atof(optarg);
|
||||
fprintf(stderr, "BER = %f\n", ber);
|
||||
|
@ -118,6 +135,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
LPCNetFreeDV *lf = lpcnet_freedv_create(direct_split);
|
||||
lpcnet_open_test_file(lf->net, "test_lpcnet_statesq.f32");
|
||||
LPCNET_QUANT *q = lf->q;
|
||||
|
||||
// this program allows us to tweak params via command line
|
||||
|
@ -130,8 +148,6 @@ int main(int argc, char **argv) {
|
|||
q->dec, q->pred, q->num_stages, q->mbest, q->bits_per_frame, dec*10, (float)q->bits_per_frame/(dec*0.01));
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fin = stdin;
|
||||
fout = stdout;
|
||||
int nbits = 0, nerrs = 0;
|
||||
char frame[q->bits_per_frame];
|
||||
int bits_read = 0;
|
||||
|
|
|
@ -241,8 +241,12 @@ void lpcnet_dump(LPCNET_DUMP *d, float x[], float features[])
|
|||
c2_Sn[i] = c2_Sn[i+c2_frame_size];
|
||||
for(i=0; i<c2_frame_size; i++)
|
||||
c2_Sn[i+c2_Sn_size-c2_frame_size] = x[i];
|
||||
|
||||
float f0, voicing, snr; int pitch_index;
|
||||
pitch_index = codec2_pitch_est(d->c2pitch, c2_Sn, &f0, &voicing, &snr);
|
||||
pitch_index = codec2_pitch_est(d->c2pitch, c2_Sn, &f0, &voicing), &snr;
|
||||
if (pitch_index >= 2*PITCH_MAX_PERIOD) pitch_index = 2*PITCH_MAX_PERIOD-1;
|
||||
if (pitch_index < 2*PITCH_MIN_PERIOD) pitch_index = 2*PITCH_MIN_PERIOD;
|
||||
|
||||
features[2*NB_BANDS] = 0.01*(pitch_index-200);
|
||||
if (d->c2voicing)
|
||||
features[2*NB_BANDS+1] = voicing;
|
||||
|
|
|
@ -58,9 +58,14 @@ int main(int argc, char **argv) {
|
|||
int logmag = 0;
|
||||
int direct_split = 0;
|
||||
|
||||
fin = stdin;
|
||||
fout = stdout;
|
||||
|
||||
/* quantiser options */
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"infile", required_argument, 0, 'i'},
|
||||
{"outfile", required_argument, 0, 'u'},
|
||||
{"decimate", required_argument, 0, 'd'},
|
||||
{"numstages", required_argument, 0, 'n'},
|
||||
{"pitchquant", required_argument, 0, 'o'},
|
||||
|
@ -73,8 +78,20 @@ int main(int argc, char **argv) {
|
|||
int c;
|
||||
int opt_index = 0;
|
||||
|
||||
while ((c = getopt_long (argc, argv, "d:n:o:p:sv", long_options, &opt_index)) != -1) {
|
||||
while ((c = getopt_long (argc, argv, "d:n:o:p:svi:u:", long_options, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
if ((fin = fopen(optarg, "rb")) == NULL) {
|
||||
fprintf(stderr, "Couldn't open input file: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if ((fout = fopen(optarg, "wb")) == NULL) {
|
||||
fprintf(stderr, "Couldn't open output file: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
dec = atoi(optarg);
|
||||
fprintf(stderr, "dec = %d\n", dec);
|
||||
|
@ -101,6 +118,7 @@ int main(int argc, char **argv) {
|
|||
break;
|
||||
default:
|
||||
fprintf(stderr,"usage: %s [Options]:\n [-d --decimation 1/2/3...]\n", argv[0]);
|
||||
fprintf(stderr," [-i --infile]\n [-u --outfile]\n");
|
||||
fprintf(stderr," [-n --numstages]\n [-o --pitchbits nBits]\n");
|
||||
fprintf(stderr," [-p --pred predCoff] [-s --split]\n");
|
||||
fprintf(stderr," [-v --verbose]\n");
|
||||
|
@ -120,9 +138,6 @@ int main(int argc, char **argv) {
|
|||
q->dec, q->pred, q->num_stages, q->mbest, q->bits_per_frame, dec*10, (float)q->bits_per_frame/(dec*0.01));
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fin = stdin;
|
||||
fout = stdout;
|
||||
|
||||
char frame[lpcnet_bits_per_frame(lf)];
|
||||
int f=0;
|
||||
int bits_written=0;
|
||||
|
|
|
@ -28,6 +28,8 @@ int lpcnet_verbose = 0;
|
|||
#define DEFAULT_PITCH_BITS 6
|
||||
#define DEFAULT_DEC 3
|
||||
|
||||
static int quantise(const float * cb, float vec[], float w[], int k, int m, float *se);
|
||||
|
||||
LPCNET_QUANT *lpcnet_quant_create(int direct_split) {
|
||||
LPCNET_QUANT *q = (LPCNET_QUANT*)malloc(sizeof(LPCNET_QUANT));
|
||||
if (q == NULL) return NULL;
|
||||
|
@ -133,7 +135,7 @@ void quant_pred_mbest(float vec_out[],
|
|||
float target[k];
|
||||
|
||||
for(i=0; i<num_stages; i++) {
|
||||
mbest_stage[i] = mbest_create(mbest_survivors, num_stages);
|
||||
mbest_stage[i] = lpcnet_mbest_create(mbest_survivors, num_stages);
|
||||
index[i] = 0;
|
||||
}
|
||||
|
||||
|
@ -150,7 +152,7 @@ void quant_pred_mbest(float vec_out[],
|
|||
/* now quantise err[] using multi-stage mbest search, preserving
|
||||
mbest_survivors at each stage */
|
||||
|
||||
mbest_search(vq, err, w, k, m[0], mbest_stage[0], index);
|
||||
lpcnet_mbest_search(vq, err, w, k, m[0], mbest_stage[0], index);
|
||||
if (lpcnet_verbose) MBEST_PRINT("Stage 1:", mbest_stage[0]);
|
||||
|
||||
for(s=1; s<num_stages; s++) {
|
||||
|
@ -172,7 +174,7 @@ void quant_pred_mbest(float vec_out[],
|
|||
}
|
||||
}
|
||||
pv(" target: ", target);
|
||||
mbest_search(&vq[s*k*MAX_ENTRIES], target, w, k, m[s], mbest_stage[s], index);
|
||||
lpcnet_mbest_search(&vq[s*k*MAX_ENTRIES], target, w, k, m[s], mbest_stage[s], index);
|
||||
}
|
||||
char str[80]; sprintf(str,"Stage %d:", s+1);
|
||||
if (lpcnet_verbose) MBEST_PRINT(str, mbest_stage[s]);
|
||||
|
@ -195,7 +197,7 @@ void quant_pred_mbest(float vec_out[],
|
|||
quant_pred_output(vec_out, indexes, err, pred, num_stages, vq, k);
|
||||
|
||||
for(i=0; i<num_stages; i++)
|
||||
mbest_destroy(mbest_stage[i]);
|
||||
lpcnet_mbest_destroy(mbest_stage[i]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -241,7 +243,7 @@ void quant_pred_output(float vec_out[],
|
|||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int quantise(const float * cb, float vec[], float w[], int k, int m, float *se)
|
||||
static int quantise(const float * cb, float vec[], float w[], int k, int m, float *se)
|
||||
/* float cb[][K]; current VQ codebook */
|
||||
/* float vec[]; vector to quantise */
|
||||
/* float w[]; weighting vector */
|
||||
|
@ -284,7 +286,7 @@ int pitch_encode(float pitch_feature, int pitch_bits) {
|
|||
// we may not need any special precautions here.
|
||||
int periods = 0.1 + 50*pitch_feature + 100;
|
||||
if (periods < PITCH_MIN_PERIOD) periods = PITCH_MIN_PERIOD;
|
||||
if (periods > PITCH_MAX_PERIOD) periods = PITCH_MAX_PERIOD;
|
||||
if (periods >= PITCH_MAX_PERIOD) periods = PITCH_MAX_PERIOD-1;
|
||||
|
||||
// should probably add rounding here
|
||||
int q = (periods - PITCH_MIN_PERIOD) >> (8 - pitch_bits);
|
||||
|
@ -293,6 +295,9 @@ int pitch_encode(float pitch_feature, int pitch_bits) {
|
|||
|
||||
float pitch_decode(int pitch_bits, int q) {
|
||||
int periods_ = (q << (8 - pitch_bits)) + PITCH_MIN_PERIOD;
|
||||
/* bit errors can push periods_ to 63*(8-6)+20 = 272 which breaks embedd layer */
|
||||
if (periods_ < PITCH_MIN_PERIOD) periods_ = PITCH_MIN_PERIOD;
|
||||
if (periods_ >= PITCH_MAX_PERIOD) periods_ = PITCH_MAX_PERIOD-1;
|
||||
return ((float)periods_ - 100.0 - 0.1)/50.0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,6 @@ void lpcnet_quant_compute_bits_per_frame(LPCNET_QUANT *q);
|
|||
extern FILE *lpcnet_fsv;
|
||||
extern int lpcnet_verbose;
|
||||
|
||||
int quantise(const float * cb, float vec[], float w[], int k, int m, float *se);
|
||||
|
||||
void quant_pred(float vec_out[], /* prev quant vector, and output */
|
||||
float vec_in[],
|
||||
float pred,
|
||||
|
|
45
src/mbest.c
45
src/mbest.c
|
@ -5,10 +5,7 @@
|
|||
DATE CREATED: Jan 2017
|
||||
|
||||
Multistage vector quantiser search algorithm that keeps multiple
|
||||
candidates from each stage.
|
||||
|
||||
TODO: A unit test with contrived examples. This is a complex algorithm and
|
||||
I am afraid I may have missed something subtle.
|
||||
candidates from each stage - LPCNet version.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -38,7 +35,7 @@
|
|||
|
||||
#include "mbest.h"
|
||||
|
||||
struct MBEST *mbest_create(int entries, int stages) {
|
||||
struct MBEST *lpcnet_mbest_create(int entries, int stages) {
|
||||
int i,j;
|
||||
struct MBEST *mbest;
|
||||
|
||||
|
@ -60,7 +57,7 @@ struct MBEST *mbest_create(int entries, int stages) {
|
|||
return mbest;
|
||||
}
|
||||
|
||||
void mbest_destroy(struct MBEST *mbest) {
|
||||
void lpcnet_mbest_destroy(struct MBEST *mbest) {
|
||||
assert(mbest != NULL);
|
||||
free(mbest->list);
|
||||
free(mbest);
|
||||
|
@ -77,7 +74,7 @@ void mbest_destroy(struct MBEST *mbest) {
|
|||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
void mbest_insert(struct MBEST *mbest, int index[], float error) {
|
||||
static void mbest_insert(struct MBEST *mbest, int index[], float error) {
|
||||
int i, j, found;
|
||||
struct MBEST_LIST *list = mbest->list;
|
||||
int entries = mbest->entries;
|
||||
|
@ -96,7 +93,7 @@ void mbest_insert(struct MBEST *mbest, int index[], float error) {
|
|||
}
|
||||
|
||||
|
||||
void mbest_print(char title[], struct MBEST *mbest) {
|
||||
void lpcnet_mbest_print(char title[], struct MBEST *mbest) {
|
||||
int i,j;
|
||||
|
||||
fprintf(stderr, "%s\n", title);
|
||||
|
@ -117,7 +114,7 @@ void mbest_print(char title[], struct MBEST *mbest) {
|
|||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
void mbest_search(
|
||||
void lpcnet_mbest_search(
|
||||
const float *cb, /* VQ codebook to search */
|
||||
float vec[], /* target vector */
|
||||
float w[], /* weighting vector */
|
||||
|
@ -143,33 +140,3 @@ void mbest_search(
|
|||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
|
||||
mbest_search450
|
||||
|
||||
Searches vec[] to a codebbook of vectors, and maintains a list of the mbest
|
||||
closest matches. Only searches the first NewAmp2_K Vectors
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
void mbest_search450(const float *cb, float vec[], float w[], int k,int shorterK, int m, struct MBEST *mbest, int index[])
|
||||
|
||||
{
|
||||
float e;
|
||||
int i,j;
|
||||
float diff;
|
||||
|
||||
for(j=0; j<m; j++) {
|
||||
e = 0.0;
|
||||
for(i=0; i<k; i++) {
|
||||
//Only search first NEWAMP2_K Vectors
|
||||
if(i<shorterK){
|
||||
diff = cb[j*k+i]-vec[i];
|
||||
e += powf(diff*w[i],2.0);
|
||||
}
|
||||
}
|
||||
index[0] = j;
|
||||
mbest_insert(mbest, index, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
src/mbest.h
16
src/mbest.h
|
@ -5,7 +5,7 @@
|
|||
DATE CREATED: Jan 2017
|
||||
|
||||
Multistage vector quantiser search algorithm that keeps multiple
|
||||
candidates from each stage.
|
||||
candidates from each stage. LPCNet version.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -43,19 +43,17 @@ struct MBEST {
|
|||
struct MBEST_LIST *list;
|
||||
};
|
||||
|
||||
struct MBEST *mbest_create(int entries, int stages);
|
||||
void mbest_destroy(struct MBEST *mbest);
|
||||
void mbest_insert(struct MBEST *mbest, int index[], float error);
|
||||
void mbest_search(const float *cb, float vec[], float w[], int k, int m, struct MBEST *mbest, int index[]);
|
||||
void mbest_search450(const float *cb, float vec[], float w[], int k,int shorterK, int m, struct MBEST *mbest, int index[]);
|
||||
void mbest_print(char title[], struct MBEST *mbest);
|
||||
struct MBEST *lpcnet_mbest_create(int entries, int stages);
|
||||
void lpcnet_mbest_destroy(struct MBEST *mbest);
|
||||
static void mbest_insert(struct MBEST *mbest, int index[], float error);
|
||||
void lpcnet_mbest_search(const float *cb, float vec[], float w[], int k, int m, struct MBEST *mbest, int index[]);
|
||||
void lpcnet_mbest_print(char title[], struct MBEST *mbest);
|
||||
|
||||
#define MBEST_PRINT_OUT
|
||||
#ifdef MBEST_PRINT_OUT
|
||||
#define MBEST_PRINT(a,b) mbest_print((a),(b))
|
||||
#define MBEST_PRINT(a,b) lpcnet_mbest_print((a),(b))
|
||||
#else
|
||||
#define MBEST_PRINT(a,b)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
16
src/nnet.c
16
src/nnet.c
|
@ -358,6 +358,16 @@ void accum_embedding(const EmbeddingLayer *layer, float *output, int input)
|
|||
}
|
||||
}
|
||||
|
||||
/* needed to replace Windows/gcc rand() with our own rand() function
|
||||
to get click free synthesised audio - not sure why */
|
||||
#define NNET_RAND_MAX 32768
|
||||
static uint32_t next = 1;
|
||||
uint16_t nnet_rand(void) {
|
||||
next = next * 1103515245 + 12345;
|
||||
uint32_t r = (next/65536) % 32768;
|
||||
return((uint16_t)r);
|
||||
}
|
||||
|
||||
int sample_from_pdf(const float *pdf, int N, float exp_boost, float pdf_floor)
|
||||
{
|
||||
int i;
|
||||
|
@ -392,10 +402,14 @@ int sample_from_pdf(const float *pdf, int N, float exp_boost, float pdf_floor)
|
|||
tmp[i] = tmp[i-1] + MAX16(0, norm*tmp[i] - pdf_floor);
|
||||
}
|
||||
/* Do the sampling (from the cdf). */
|
||||
r = tmp[N-1] * ((float)rand()/RAND_MAX);
|
||||
float annr = (float)nnet_rand();
|
||||
float arand = (annr/NNET_RAND_MAX);
|
||||
r = tmp[N-1] * arand;
|
||||
|
||||
for (i=0;i<N-1;i++)
|
||||
{
|
||||
if (r < tmp[i]) return i;
|
||||
}
|
||||
//fprintf(stderr, "DUAL_FC_OUT_SIZE: %d annr: %f arand: %f\n", DUAL_FC_OUT_SIZE, annr, arand);
|
||||
return N-1;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ int main(int argc, char **argv) {
|
|||
if (strcmp(argv[1], "-") == 0)
|
||||
f1 = stdin;
|
||||
else {
|
||||
f1 = fopen(argv[1], "r");
|
||||
f1 = fopen(argv[1], "rb");
|
||||
if (f1 == NULL) {
|
||||
fprintf(stderr,"Error opening input .s16 16kHz speech input file: %s\n", argv[1]);
|
||||
exit(1);
|
||||
|
@ -60,7 +60,7 @@ int main(int argc, char **argv) {
|
|||
if (strcmp(argv[2], "-") == 0)
|
||||
ffeat = stdout;
|
||||
else {
|
||||
ffeat = fopen(argv[2], "w");
|
||||
ffeat = fopen(argv[2], "wb");
|
||||
if (ffeat == NULL) {
|
||||
fprintf(stderr,"Error opening output feature file: %s\n", argv[2]);
|
||||
exit(1);
|
||||
|
@ -71,10 +71,12 @@ int main(int argc, char **argv) {
|
|||
float features[LPCNET_NB_FEATURES];
|
||||
int i;
|
||||
int f=0;
|
||||
int nread;
|
||||
|
||||
while (1) {
|
||||
/* note one frame delay */
|
||||
for (i=0;i<FRAME_SIZE;i++) x[i] = d->tmp[i];
|
||||
int nread = fread(&d->tmp, sizeof(short), FRAME_SIZE, f1);
|
||||
nread = fread(&d->tmp, sizeof(short), FRAME_SIZE, f1);
|
||||
if (nread != FRAME_SIZE) break;
|
||||
lpcnet_dump(d,x,features);
|
||||
fwrite(features, sizeof(float), LPCNET_NB_FEATURES, ffeat);
|
||||
|
|
|
@ -35,15 +35,16 @@
|
|||
int main(int argc, char **argv) {
|
||||
FILE *fin, *fout;
|
||||
LPCNetState *net;
|
||||
|
||||
int logmag = 0;
|
||||
|
||||
int o = 0;
|
||||
int opt_idx = 0;
|
||||
while( o != -1 ) {
|
||||
static struct option long_opts[] = {
|
||||
{"mag", no_argument,0, 'i'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{"mag", no_argument,0, 'i'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
o = getopt_long(argc,argv,"ih",long_opts,&opt_idx);
|
||||
|
||||
|
@ -59,8 +60,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
int dx = optind;
|
||||
|
||||
if ((argc - dx) < 2)
|
||||
{
|
||||
if ((argc - dx) < 2) {
|
||||
helpmsg:
|
||||
fprintf(stderr, "usage: test_lpcnet [--mag] <features.f32> <output.pcm>\n");
|
||||
return 0;
|
||||
|
@ -85,6 +85,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
net = lpcnet_create();
|
||||
lpcnet_open_test_file(net, "test_lpcnet_states.f32");
|
||||
|
||||
while (1) {
|
||||
float in_features[NB_TOTAL_FEATURES];
|
||||
float features[NB_FEATURES];
|
||||
|
|
Loading…
Reference in New Issue