├── .gitignore ├── HRA_112_112.h ├── Makefile ├── README.md ├── _kiss_fft_guts.h ├── bpf.h ├── bpfb.h ├── c2wideband.h ├── codebook.c ├── codebookd.c ├── codebookdt.c ├── codebookge.c ├── codebookjvm.c ├── codebooklspmelvq.c ├── codebookmel.c ├── codebooknewamp1.c ├── codebooknewamp1_energy.c ├── codebookres.c ├── codebookvq.c ├── codec2.c ├── codec2.h ├── codec2_fdmdv.h ├── codec2_fft.c ├── codec2_fft.h ├── codec2_internal.h ├── codec2_ofdm.h ├── comp.h ├── comp_prim.h ├── defines.h ├── dump.c ├── dump.h ├── gp_interleaver.c ├── gp_interleaver.h ├── interldpc.c ├── interldpc.h ├── interp.c ├── interp.h ├── kiss_fft.c ├── kiss_fft.h ├── kiss_fftr.c ├── kiss_fftr.h ├── lpc.c ├── lpc.h ├── lsp.c ├── lsp.h ├── machdep.h ├── main.c ├── mbest.c ├── mbest.h ├── modem_stats.c ├── modem_stats.h ├── mpdecode_core.c ├── mpdecode_core.h ├── newamp1.c ├── newamp1.h ├── nlp.c ├── nlp.h ├── ofdm.c ├── ofdm_bpf_coeff.h ├── ofdm_internal.h ├── os.h ├── pack.c ├── phase.c ├── phase.h ├── postfilter.c ├── postfilter.h ├── quantise.c ├── quantise.h ├── sine.c ├── sine.h ├── test_bits_ofdm.h └── version.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | m17_udp_listener 3 | -------------------------------------------------------------------------------- /HRA_112_112.h: -------------------------------------------------------------------------------- 1 | /* 2 | FILE....: ../src/HRA_112_112.h 3 | 4 | Static arrays for CML LDPC, generated by ldpc_gen_h_file.m. 5 | */ 6 | 7 | #define HRA_112_112_NUMBERPARITYBITS 112 8 | #define HRA_112_112_MAX_ROW_WEIGHT 3 9 | #define HRA_112_112_CODELENGTH 224 10 | #define HRA_112_112_NUMBERROWSHCOLS 112 11 | #define HRA_112_112_MAX_COL_WEIGHT 3 12 | #define HRA_112_112_DEC_TYPE 0 13 | #define HRA_112_112_MAX_ITER 100 14 | 15 | double HRA_112_112_H_rows[] = { 16 | 22, 18, 15, 63, 16, 13, 1, 2, 29, 25, 28, 4, 36, 10, 38, 7, 60, 23, 11, 38, 28, 1, 12, 31, 57, 45, 57, 30, 23, 59, 67, 14, 16, 4, 14, 62, 15, 50, 7, 70, 64, 6, 42, 48, 9, 31, 19, 40, 49, 2, 25, 3, 41, 49, 36, 9, 29, 39, 31, 5, 17, 1, 29, 25, 11, 21, 18, 2, 8, 22, 39, 15, 8, 22, 13, 3, 19, 4, 21, 62, 34, 43, 6, 24, 17, 60, 8, 74, 6, 44, 60, 10, 33, 12, 26, 24, 45, 81, 69, 80, 41, 28, 23, 5, 10, 20, 52, 18, 13, 86, 3, 7, 59, 21, 65, 72, 34, 37, 26, 55, 47, 48, 34, 5, 44, 47, 68, 96, 82, 111, 61, 74, 30, 17, 55, 98, 81, 66, 89, 35, 74, 82, 91, 51, 55, 51, 30, 89, 61, 75, 40, 71, 73, 11, 56, 54, 19, 47, 94, 69, 64, 20, 64, 12, 54, 77, 42, 88, 36, 52, 90, 63, 70, 27, 32, 73, 91, 32, 56, 46, 9, 78, 51, 68, 88, 67, 20, 43, 40, 14, 66, 86, 39, 97, 38, 27, 50, 84, 54, 92, 61, 46, 67, 24, 58, 35, 58, 37, 98, 85, 73, 84, 48, 35, 57, 16, 26, 37, 65, 32, 72, 95, 107, 33, 77, 33, 85, 105, 106, 75, 56, 71, 79, 59, 52, 105, 79, 90, 93, 100, 88, 112, 86, 80, 65, 42, 106, 100, 93, 94, 99, 97, 93, 101, 111, 99, 83, 53, 85, 95, 108, 107, 41, 109, 84, 78, 104, 101, 69, 110, 98, 103, 80, 83, 77, 71, 76, 78, 87, 102, 104, 95, 96, 83, 87, 50, 110, 103, 112, 45, 58, 70, 94, 91, 89, 81, 101, 82, 63, 72, 100, 97, 76, 112, 53, 105, 49, 75, 109, 102, 66, 111, 68, 87, 92, 79, 96, 43, 90, 44, 110, 99, 102, 92, 103, 106, 62, 53, 27, 46, 108, 104, 107, 108, 109, 76 17 | }; 18 | 19 | double HRA_112_112_H_cols[] = { 20 | 7, 8, 52, 12, 12, 42, 16, 69, 45, 14, 19, 23, 6, 32, 3, 5, 22, 2, 45, 50, 2, 1, 18, 84, 10, 7, 62, 11, 9, 21, 24, 63, 2, 5, 28, 13, 6, 15, 58, 39, 39, 22, 76, 13, 26, 68, 9, 10, 49, 38, 32, 11, 34, 44, 8, 7, 25, 67, 1, 17, 19, 36, 4, 41, 3, 26, 31, 15, 45, 40, 8, 4, 41, 20, 6, 53, 1, 42, 9, 20, 25, 17, 33, 41, 3, 19, 55, 17, 27, 14, 31, 88, 15, 26, 36, 16, 28, 24, 27, 16, 30, 56, 48, 43, 4, 5, 38, 37, 40, 46, 18, 18, 22, 50, 76, 34, 60, 83, 39, 73, 56, 92, 42, 52, 75, 35, 37, 33, 61, 67, 47, 75, 66, 70, 29, 92, 51, 95, 84, 21, 57, 28, 46, 66, 93, 11, 94, 55, 96, 20, 71, 48, 53, 43, 82, 90, 66, 90, 14, 44, 54, 62, 34, 58, 81, 53, 23, 43, 27, 93, 10, 86, 37, 80, 60, 49, 21, 79, 74, 72, 48, 61, 40, 76, 64, 29, 38, 79, 51, 54, 13, 49, 72, 30, 50, 86, 35, 80, 61, 56, 36, 59, 65, 91, 25, 47, 58, 59, 78, 47, 32, 24, 44, 86, 64, 57, 12, 23, 109, 107, 85, 63, 31, 65, 62, 68, 111, 78, 104, 89, 112, 87, 69, 105, 65, 94, 109, 78, 72, 104, 85, 108, 77, 106, 79, 74, 103, 96, 64, 105, 105, 102, 63, 35, 59, 108, 112, 81, 102, 57, 106, 83, 81, 77, 101, 55, 94, 96, 97, 106, 46, 101, 83, 85, 71, 107, 104, 87, 33, 67, 103, 95, 30, 91, 89, 103, 75, 51, 107, 87, 91, 89, 99, 68, 52, 109, 99, 88, 84, 112, 54, 70, 92, 100, 98, 74, 60, 100, 98, 110, 90, 73, 71, 95, 70, 100, 29, 69, 110, 93, 82, 97, 98, 77, 73, 99, 101, 108, 82, 102, 111, 110, 111, 97, 88, 80 21 | }; 22 | 23 | double HRA_112_112_input[] = { 24 | -5.7868467875518395, -6.340739523388657, 3.6654768375589399, 4.1452438183910827, -4.6746135252043111, -4.8353634065473701, -6.0729133999971285, 4.0335561282226271, -6.1114855315699135, 4.1029513876344916, -4.6481634503883624, 5.7650915278538646, 6.5567610490570312, 5.1810523550761207, 3.4789051916752669, 4.2678848515507122, 4.0314705275547089, 6.0297078342283799, 4.9101169653222163, -6.4577297598332324, -7.4273487270443095, 3.472130985267488, -6.5346233967202254, 7.5312028458762414, -5.2618748211985915, 6.4198074556254969, 3.7500207659511484, 5.4040878141701141, 5.7554260586578803, 3.3973620625026886, 7.1815269888532907, 5.0031747952824963, 5.1377243276145599, 5.385229914081755, -0.61384230253605643, 0.46954911161835722, 3.5182611493679663, 3.393698829567279, 6.147483866535171, 3.8374563885989228, 1.3663773773557015, -4.0917661778352352, -3.2968298202652835, -6.0371912041431148, -8.4279246895331781, -0.98556788606912304, -3.515442879601625, 4.2642476942514875, -5.5905016743156972, 3.6920101668161727, -4.035860013856472, 5.3290190966269995, -2.9729656070594057, -2.5054371041338537, 6.8683150013190115, -7.1109038108500098, 6.7301890172695158, 2.5782062882356374, 4.4161464916633282, 2.2692851122935322, -1.3682527221025034, 3.0794629981237631, -7.8655412763279973, 1.1479897597156494, 0.22370696314520414, 1.1222453403894148, -3.1335220808128219, -3.8352985265277089, -1.2463521619727009, 2.9511814015293218, -8.668811041413111, 3.0185610517830548, -6.9592962351476091, 3.9653416636625414, -3.9384322074229408, 1.6789027505247516, 2.9579632055145502, -2.1212672699995125, -3.8892168640945193, 7.516114544807583, -0.84285604179011253, 4.1295390817792512, 0.26093278495228162, -3.6071666499996047, -0.065323173773821908, -1.9146584862100915, 4.7951161310834367, 5.5440002982088803, 3.5917539980319364, -0.81416023563684481, -2.6588977758747721, -3.0404494660606227, 4.5389936536649662, 2.7870543501114082, 3.5622966707453889, 5.1982116994791161, 2.4775319712999302, 0.70541080068007755, 0.89622787904518464, 4.3789020039207758, -2.4976040580619445, -0.7201255450933205, 4.2071986295109394, -5.2418379271657001, -4.092365654835163, -4.3510198326542557, 3.7404138637596001, 1.2496890930262492, -7.1053909336149728, -4.8888279905256748, -6.3523901926735249, -1.8757980409249277, 3.6256343910366273, -3.6165398844758228, -0.38322352317510561, -0.84747550047769449, -1.2717892264620718, -2.3899810721111154, 4.1368500898628637, 3.0440159002314924, 3.4235543074310728, -2.146097053557551, -1.7537615307751735, -1.0280987119225686, 4.9009275359419204, 5.0046047156368116, -0.47700833783807428, -4.5989492891875567, 1.4154839158712684, 0.33410724822249849, -4.771937854508927, -1.1817007924012972, -2.5960865023249302, 0.30422629502493687, -2.2097849377516763, -4.343244940878872, 1.9464288912612249, -9.0976989032526809, -8.6454142547592685, -1.8164317522989997, 2.2780845702169961, -4.8775405042023356, -0.61834757216625769, -1.985554501661331, -0.87599558657596699, -8.0610201531782124, -5.9847574894882554, -10.365536404711067, 2.9782191161319376, -6.9443820217795169, 0.72935566343949876, -4.5326632961380664, 1.1307250622386897, -4.0853969692041314, 5.4926924507347596, 5.6722555096362042, -2.5069992226180222, 2.0460084066662092, 2.5375899018238197, -3.5264293517823679, 3.2103083878487557, 5.793713046583183, -2.7633653287377995, 6.482851815629938, -1.2471646528152021, 3.0010491047486085, 0.29072399293868856, -4.0686659405747738, -2.6253508133431289, -6.3896590677017171, 5.7054076607727886, 4.3053292399977092, 2.2372599539047151, -4.8975607398431897, 5.8124794005531406, -0.69648233429781359, 5.5509723605410004, 2.0900652762982923, -4.7944253330785118, -2.9224693872108287, 6.0218579796888303, 4.7027436964063387, -4.1564871824868659, -1.324779121305123, 0.38031612697724176, -0.69335927945709175, -0.4028295686263082, 2.0967669774299189, 2.7947186736855909, 2.1473880039026203, 6.368702510367898, -3.0691782325684049, 1.6125827087903837, 3.5925359669662518, 5.178224480471127, -2.5070763799556617, 4.4280512389456632, -6.5385259627250134, 2.8047951999607603, -3.0185715385981151, -0.33348983718789993, -4.3285127692183556, -7.9609407359365134, 7.064973172264966, 0.95714371675898213, -5.5481272272415545, -1.6024149180708045, -4.5740915350065992, -1.5117120929647263, 1.9996824689403947, 5.9527526663437724, 5.0239857792804967, 6.2677418491798784, -1.9758548902654505, 2.1709284879472324, 2.5054563138111572, 4.4483685492445115, 3.2098357106645676, -4.5306213859481099, 1.1291114493451548, 1.5827945023160555, -5.2733490015732292, 5.0664709821503457, 1.9652801880230106 25 | }; 26 | 27 | char HRA_112_112_detected_data[] = { 28 | 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 29 | }; 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Project: M17_UDP_listener 2 | 3 | CPP = g++ 4 | CC = gcc 5 | WINDRES = 6 | OBJ = main.o codebook.o codebookd.o codebookdt.o codebookge.o codebookjvm.o codebooklspmelvq.o codebookmel.o codebooknewamp1.o codebooknewamp1_energy.o codebookres.o codebookvq.o codec2.o codec2_fft.o gp_interleaver.o interldpc.o interp.o kiss_fft.o kiss_fftr.o lpc.o lsp.o mbest.o modem_stats.o mpdecode_core.o newamp1.o nlp.o ofdm.o pack.o phase.o postfilter.o quantise.o sine.o 7 | LINKOBJ = main.o codebook.o codebookd.o codebookdt.o codebookge.o codebookjvm.o codebooklspmelvq.o codebookmel.o codebooknewamp1.o codebooknewamp1_energy.o codebookres.o codebookvq.o codec2.o codec2_fft.o gp_interleaver.o interp.o kiss_fft.o kiss_fftr.o lpc.o lsp.o mbest.o modem_stats.o mpdecode_core.o newamp1.o nlp.o ofdm.o pack.o phase.o postfilter.o quantise.o sine.o 8 | LIBS = -static-libgcc -lm 9 | INCS = 10 | CXXINCS = 11 | BIN = m17_udp_listener 12 | CXXFLAGS = $(CXXINCS) -march=native -msse3 -O2 -std=gnu99 13 | CFLAGS = $(INCS) -march=native -msse3 -O2 -std=gnu99 14 | RM = rm -f 15 | 16 | .PHONY: all all-before all-after clean clean-custom 17 | 18 | all: all-before $(BIN) all-after 19 | 20 | clean: clean-custom 21 | ${RM} $(OBJ) $(BIN) 22 | 23 | $(BIN): $(OBJ) 24 | $(CC) $(LINKOBJ) -o $(BIN) $(LIBS) 25 | 26 | %.o: %.c 27 | $(CC) $(CFLAGS) -c $^ -o $@ 28 | 29 | run: 30 | ./m17_udp_listener 17000 | aplay -t raw -f S16_LE -r 8000 -c 1 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # M17_UDP 2 | Receives voice packets via UDP and allows to play them back using aplay. 3 | 4 | # Usage 5 | ./m17_udp_listener | aplay -t raw -f S16_LE -r 8000 -c 1 6 | -------------------------------------------------------------------------------- /_kiss_fft_guts.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2010, Mark Borgerding 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | * 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. 10 | * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | 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 COPYRIGHT OWNER 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. 13 | */ 14 | 15 | /* kiss_fft.h 16 | defines kiss_fft_scalar as either short or a float type 17 | and defines 18 | typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ 19 | #include "kiss_fft.h" 20 | #include 21 | 22 | #define MAXFACTORS 32 23 | /* e.g. an fft of length 128 has 4 factors 24 | as far as kissfft is concerned 25 | 4*4*4*2 26 | */ 27 | 28 | struct kiss_fft_state{ 29 | int nfft; 30 | int inverse; 31 | int factors[2*MAXFACTORS]; 32 | kiss_fft_cpx twiddles[1]; 33 | }; 34 | 35 | /* 36 | Explanation of macros dealing with complex math: 37 | 38 | C_MUL(m,a,b) : m = a*b 39 | C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise 40 | C_SUB( res, a,b) : res = a - b 41 | C_SUBFROM( res , a) : res -= a 42 | C_ADDTO( res , a) : res += a 43 | * */ 44 | #ifdef FIXED_POINT 45 | #if (FIXED_POINT==32) 46 | # define FRACBITS 31 47 | # define SAMPPROD int64_t 48 | #define SAMP_MAX 2147483647 49 | #else 50 | # define FRACBITS 15 51 | # define SAMPPROD int32_t 52 | #define SAMP_MAX 32767 53 | #endif 54 | 55 | #define SAMP_MIN -SAMP_MAX 56 | 57 | #if defined(CHECK_OVERFLOW) 58 | # define CHECK_OVERFLOW_OP(a,op,b) \ 59 | if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ 60 | fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } 61 | #endif 62 | 63 | 64 | # define smul(a,b) ( (SAMPPROD)(a)*(b) ) 65 | # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) 66 | 67 | # define S_MUL(a,b) sround( smul(a,b) ) 68 | 69 | # define C_MUL(m,a,b) \ 70 | do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ 71 | (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) 72 | 73 | # define DIVSCALAR(x,k) \ 74 | (x) = sround( smul( x, SAMP_MAX/k ) ) 75 | 76 | # define C_FIXDIV(c,div) \ 77 | do { DIVSCALAR( (c).r , div); \ 78 | DIVSCALAR( (c).i , div); }while (0) 79 | 80 | # define C_MULBYSCALAR( c, s ) \ 81 | do{ (c).r = sround( smul( (c).r , s ) ) ;\ 82 | (c).i = sround( smul( (c).i , s ) ) ; }while(0) 83 | 84 | #else /* not FIXED_POINT*/ 85 | 86 | # define S_MUL(a,b) ( (a)*(b) ) 87 | #define C_MUL(m,a,b) \ 88 | do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ 89 | (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) 90 | # define C_FIXDIV(c,div) /* NOOP */ 91 | # define C_MULBYSCALAR( c, s ) \ 92 | do{ (c).r *= (s);\ 93 | (c).i *= (s); }while(0) 94 | #endif 95 | 96 | #ifndef CHECK_OVERFLOW_OP 97 | # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ 98 | #endif 99 | 100 | #define C_ADD( res, a,b)\ 101 | do { \ 102 | CHECK_OVERFLOW_OP((a).r,+,(b).r)\ 103 | CHECK_OVERFLOW_OP((a).i,+,(b).i)\ 104 | (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ 105 | }while(0) 106 | #define C_SUB( res, a,b)\ 107 | do { \ 108 | CHECK_OVERFLOW_OP((a).r,-,(b).r)\ 109 | CHECK_OVERFLOW_OP((a).i,-,(b).i)\ 110 | (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ 111 | }while(0) 112 | #define C_ADDTO( res , a)\ 113 | do { \ 114 | CHECK_OVERFLOW_OP((res).r,+,(a).r)\ 115 | CHECK_OVERFLOW_OP((res).i,+,(a).i)\ 116 | (res).r += (a).r; (res).i += (a).i;\ 117 | }while(0) 118 | 119 | #define C_SUBFROM( res , a)\ 120 | do {\ 121 | CHECK_OVERFLOW_OP((res).r,-,(a).r)\ 122 | CHECK_OVERFLOW_OP((res).i,-,(a).i)\ 123 | (res).r -= (a).r; (res).i -= (a).i; \ 124 | }while(0) 125 | 126 | 127 | #ifdef FIXED_POINT 128 | # define KISS_FFT_COS(phase) floorf(.5+SAMP_MAX * cosf (phase)) 129 | # define KISS_FFT_SIN(phase) floorf(.5+SAMP_MAX * sinf (phase)) 130 | # define HALF_OF(x) ((x)>>1) 131 | #elif defined(USE_SIMD) 132 | # define KISS_FFT_COS(phase) _mm_set1_ps( cosf(phase) ) 133 | # define KISS_FFT_SIN(phase) _mm_set1_ps( sinf(phase) ) 134 | # define HALF_OF(x) ((x)*_mm_set1_ps(.5)) 135 | #else 136 | # define KISS_FFT_COS(phase) (kiss_fft_scalar) cosf(phase) 137 | # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sinf(phase) 138 | # define HALF_OF(x) ((x)*.5) 139 | #endif 140 | 141 | #define kf_cexp(x,phase) \ 142 | do{ \ 143 | (x)->r = KISS_FFT_COS(phase);\ 144 | (x)->i = KISS_FFT_SIN(phase);\ 145 | }while(0) 146 | 147 | 148 | /* a debugging function */ 149 | #define pcpx(c)\ 150 | fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) 151 | 152 | 153 | #ifdef KISS_FFT_USE_ALLOCA 154 | // define this to allow use of alloca instead of malloc for temporary buffers 155 | // Temporary buffers are used in two case: 156 | // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 157 | // 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. 158 | #include 159 | #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) 160 | #define KISS_FFT_TMP_FREE(ptr) 161 | #else 162 | #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) 163 | #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) 164 | #endif 165 | -------------------------------------------------------------------------------- /bpf.h: -------------------------------------------------------------------------------- 1 | #define BPF_N 101 2 | 3 | float bpf[]={ 4 | 0.002174, 5 | 0.003245, 6 | 0.002147, 7 | 0.001866, 8 | 0.002764, 9 | 0.000567, 10 | -0.001641, 11 | -0.000565, 12 | -0.002415, 13 | -0.005837, 14 | -0.003620, 15 | -0.002828, 16 | -0.006268, 17 | -0.002787, 18 | 0.001963, 19 | -0.001234, 20 | 0.001446, 21 | 0.009200, 22 | 0.005331, 23 | 0.003521, 24 | 0.011821, 25 | 0.006951, 26 | -0.002015, 27 | 0.005137, 28 | 0.001828, 29 | -0.013390, 30 | -0.007058, 31 | -0.003273, 32 | -0.020458, 33 | -0.014321, 34 | 0.001751, 35 | -0.012891, 36 | -0.009730, 37 | 0.018993, 38 | 0.008544, 39 | 0.000534, 40 | 0.035755, 41 | 0.029074, 42 | -0.001192, 43 | 0.030852, 44 | 0.030983, 45 | -0.029834, 46 | -0.009550, 47 | 0.011945, 48 | -0.081971, 49 | -0.082875, 50 | 0.000423, 51 | -0.133526, 52 | -0.211778, 53 | 0.182628, 54 | 0.514906, 55 | 0.182628, 56 | -0.211778, 57 | -0.133526, 58 | 0.000423, 59 | -0.082875, 60 | -0.081971, 61 | 0.011945, 62 | -0.009550, 63 | -0.029834, 64 | 0.030983, 65 | 0.030852, 66 | -0.001192, 67 | 0.029074, 68 | 0.035755, 69 | 0.000534, 70 | 0.008544, 71 | 0.018993, 72 | -0.009730, 73 | -0.012891, 74 | 0.001751, 75 | -0.014321, 76 | -0.020458, 77 | -0.003273, 78 | -0.007058, 79 | -0.013390, 80 | 0.001828, 81 | 0.005137, 82 | -0.002015, 83 | 0.006951, 84 | 0.011821, 85 | 0.003521, 86 | 0.005331, 87 | 0.009200, 88 | 0.001446, 89 | -0.001234, 90 | 0.001963, 91 | -0.002787, 92 | -0.006268, 93 | -0.002828, 94 | -0.003620, 95 | -0.005837, 96 | -0.002415, 97 | -0.000565, 98 | -0.001641, 99 | 0.000567, 100 | 0.002764, 101 | 0.001866, 102 | 0.002147, 103 | 0.003245, 104 | 0.002174 105 | }; 106 | 107 | -------------------------------------------------------------------------------- /bpfb.h: -------------------------------------------------------------------------------- 1 | #define BPFB_N 101 2 | 3 | float bpfb[]={ 4 | 0.003795, 5 | 0.006827, 6 | 0.002261, 7 | 0.002523, 8 | 0.005758, 9 | -0.000264, 10 | -0.000674, 11 | 0.003113, 12 | -0.004144, 13 | -0.004923, 14 | 0.000043, 15 | -0.008017, 16 | -0.008711, 17 | -0.001802, 18 | -0.010210, 19 | -0.010428, 20 | -0.000899, 21 | -0.009413, 22 | -0.009072, 23 | 0.003469, 24 | -0.005335, 25 | -0.004828, 26 | 0.010724, 27 | 0.000941, 28 | 0.000708, 29 | 0.018957, 30 | 0.007084, 31 | 0.004825, 32 | 0.025418, 33 | 0.010147, 34 | 0.004452, 35 | 0.027434, 36 | 0.007550, 37 | -0.002861, 38 | 0.023483, 39 | -0.001944, 40 | -0.018138, 41 | 0.014122, 42 | -0.017583, 43 | -0.040768, 44 | 0.002598, 45 | -0.036604, 46 | -0.069541, 47 | -0.004273, 48 | -0.054876, 49 | -0.107289, 50 | 0.010068, 51 | -0.068052, 52 | -0.200119, 53 | 0.207287, 54 | 0.597150, 55 | 0.207287, 56 | -0.200119, 57 | -0.068052, 58 | 0.010068, 59 | -0.107289, 60 | -0.054876, 61 | -0.004273, 62 | -0.069541, 63 | -0.036604, 64 | 0.002598, 65 | -0.040768, 66 | -0.017583, 67 | 0.014122, 68 | -0.018138, 69 | -0.001944, 70 | 0.023483, 71 | -0.002861, 72 | 0.007550, 73 | 0.027434, 74 | 0.004452, 75 | 0.010147, 76 | 0.025418, 77 | 0.004825, 78 | 0.007084, 79 | 0.018957, 80 | 0.000708, 81 | 0.000941, 82 | 0.010724, 83 | -0.004828, 84 | -0.005335, 85 | 0.003469, 86 | -0.009072, 87 | -0.009413, 88 | -0.000899, 89 | -0.010428, 90 | -0.010210, 91 | -0.001802, 92 | -0.008711, 93 | -0.008017, 94 | 0.000043, 95 | -0.004923, 96 | -0.004144, 97 | 0.003113, 98 | -0.000674, 99 | -0.000264, 100 | 0.005758, 101 | 0.002523, 102 | 0.002261, 103 | 0.006827, 104 | 0.003795 105 | }; -------------------------------------------------------------------------------- /c2wideband.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: c2wideband.h 3 | * Author: phil 4 | * 5 | * Created on 02 July 2017, 20:42 6 | */ 7 | 8 | #ifndef C2WIDEBAND_H 9 | #define C2WIDEBAND_H 10 | 11 | #include "defines.h" 12 | #include "phase.h" 13 | #include "quantise.h" 14 | #include "newamp1.h" 15 | #include "codec2_internal.h" 16 | 17 | #define C2WB_K 30 /* rate K vector length */ 18 | #define C2WB_FS 16000 19 | 20 | #define C2WB_NT 8 /* number of blocks in time = 160ms blocks */ 21 | #define C2WB_TF 0.02 /* 20ms frames */ 22 | #define C2WB_DEC 2 /* decimation factor */ 23 | #define C2WB_SPERF 30 /* samples per frame */ 24 | //TODO: decide what this is 25 | #define C2WB_BPERF 256 /* bits per frame */ 26 | 27 | 28 | typedef struct { 29 | int rmap[C2WB_K * C2WB_NT]; 30 | int cmap[C2WB_K * C2WB_NT]; 31 | } WIDEBAND_MAP; 32 | 33 | 34 | 35 | void codec2_decode_wb(struct CODEC2 *c2, short speech[], const unsigned char * bits); 36 | 37 | void calculate_Am_freqs_kHz(float Wo, int L, float p_Am_freqs_kHz[]); 38 | void resample_const_rate_f_mel(C2CONST *c2const, MODEL * model, float K, float* rate_K_surface, float* rate_K_sample_freqs_kHz); 39 | void correct_rate_K_vec(MODEL *model, float rate_K_vec[], float rate_K_sample_freqs_kHz[], float Am_freqs_kHz[], float orig_AmdB[], int K, float Wo, int L, int Fs, float rate_K_vec_corrected[]); 40 | void batch_rate_K_dct2(C2CONST *c2const, MODEL model_frames[], int frames, int vq_en, int plots, int* voicing, float *mean_); 41 | void rate_K_dct2(C2CONST *c2const, int n_block_frames, MODEL model_block[n_block_frames], WIDEBAND_MAP * wb_map); 42 | void wideband_enc_dec(C2CONST *c2const, int n_block_frames, MODEL model_block[], WIDEBAND_MAP * wb_map, 43 | MODEL model_block_[], float * p_dct2_sd, int * p_qn , float rate_K_surface_block[][C2WB_K], float rate_K_surface_block_[][C2WB_K]); 44 | void codec2_decode_wb(struct CODEC2 *c2, short speech[], const unsigned char * bits); 45 | void codec2_encode_wb(struct CODEC2 *c2, unsigned char * bits, short speech[]); 46 | void experiment_rate_K_dct2(C2CONST *c2const, MODEL model_frames[], int frames); 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif /* C2WIDEBAND_H */ 56 | 57 | -------------------------------------------------------------------------------- /codebook.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* codebook/lsp1.txt */ 11 | static const float codes0[] = { 12 | 225, 13 | 250, 14 | 275, 15 | 300, 16 | 325, 17 | 350, 18 | 375, 19 | 400, 20 | 425, 21 | 450, 22 | 475, 23 | 500, 24 | 525, 25 | 550, 26 | 575, 27 | 600 28 | }; 29 | /* codebook/lsp2.txt */ 30 | static const float codes1[] = { 31 | 325, 32 | 350, 33 | 375, 34 | 400, 35 | 425, 36 | 450, 37 | 475, 38 | 500, 39 | 525, 40 | 550, 41 | 575, 42 | 600, 43 | 625, 44 | 650, 45 | 675, 46 | 700 47 | }; 48 | /* codebook/lsp3.txt */ 49 | static const float codes2[] = { 50 | 500, 51 | 550, 52 | 600, 53 | 650, 54 | 700, 55 | 750, 56 | 800, 57 | 850, 58 | 900, 59 | 950, 60 | 1000, 61 | 1050, 62 | 1100, 63 | 1150, 64 | 1200, 65 | 1250 66 | }; 67 | /* codebook/lsp4.txt */ 68 | static const float codes3[] = { 69 | 700, 70 | 800, 71 | 900, 72 | 1000, 73 | 1100, 74 | 1200, 75 | 1300, 76 | 1400, 77 | 1500, 78 | 1600, 79 | 1700, 80 | 1800, 81 | 1900, 82 | 2000, 83 | 2100, 84 | 2200 85 | }; 86 | /* codebook/lsp5.txt */ 87 | static const float codes4[] = { 88 | 950, 89 | 1050, 90 | 1150, 91 | 1250, 92 | 1350, 93 | 1450, 94 | 1550, 95 | 1650, 96 | 1750, 97 | 1850, 98 | 1950, 99 | 2050, 100 | 2150, 101 | 2250, 102 | 2350, 103 | 2450 104 | }; 105 | /* codebook/lsp6.txt */ 106 | static const float codes5[] = { 107 | 1100, 108 | 1200, 109 | 1300, 110 | 1400, 111 | 1500, 112 | 1600, 113 | 1700, 114 | 1800, 115 | 1900, 116 | 2000, 117 | 2100, 118 | 2200, 119 | 2300, 120 | 2400, 121 | 2500, 122 | 2600 123 | }; 124 | /* codebook/lsp7.txt */ 125 | static const float codes6[] = { 126 | 1500, 127 | 1600, 128 | 1700, 129 | 1800, 130 | 1900, 131 | 2000, 132 | 2100, 133 | 2200, 134 | 2300, 135 | 2400, 136 | 2500, 137 | 2600, 138 | 2700, 139 | 2800, 140 | 2900, 141 | 3000 142 | }; 143 | /* codebook/lsp8.txt */ 144 | static const float codes7[] = { 145 | 2300, 146 | 2400, 147 | 2500, 148 | 2600, 149 | 2700, 150 | 2800, 151 | 2900, 152 | 3000 153 | }; 154 | /* codebook/lsp9.txt */ 155 | static const float codes8[] = { 156 | 2500, 157 | 2600, 158 | 2700, 159 | 2800, 160 | 2900, 161 | 3000, 162 | 3100, 163 | 3200 164 | }; 165 | /* codebook/lsp10.txt */ 166 | static const float codes9[] = { 167 | 2900, 168 | 3100, 169 | 3300, 170 | 3500 171 | }; 172 | 173 | const struct lsp_codebook lsp_cb[] = { 174 | /* codebook/lsp1.txt */ 175 | { 176 | 1, 177 | 4, 178 | 16, 179 | codes0 180 | }, 181 | /* codebook/lsp2.txt */ 182 | { 183 | 1, 184 | 4, 185 | 16, 186 | codes1 187 | }, 188 | /* codebook/lsp3.txt */ 189 | { 190 | 1, 191 | 4, 192 | 16, 193 | codes2 194 | }, 195 | /* codebook/lsp4.txt */ 196 | { 197 | 1, 198 | 4, 199 | 16, 200 | codes3 201 | }, 202 | /* codebook/lsp5.txt */ 203 | { 204 | 1, 205 | 4, 206 | 16, 207 | codes4 208 | }, 209 | /* codebook/lsp6.txt */ 210 | { 211 | 1, 212 | 4, 213 | 16, 214 | codes5 215 | }, 216 | /* codebook/lsp7.txt */ 217 | { 218 | 1, 219 | 4, 220 | 16, 221 | codes6 222 | }, 223 | /* codebook/lsp8.txt */ 224 | { 225 | 1, 226 | 3, 227 | 8, 228 | codes7 229 | }, 230 | /* codebook/lsp9.txt */ 231 | { 232 | 1, 233 | 3, 234 | 8, 235 | codes8 236 | }, 237 | /* codebook/lsp10.txt */ 238 | { 239 | 1, 240 | 2, 241 | 4, 242 | codes9 243 | }, 244 | { 0, 0, 0, 0 } 245 | }; 246 | -------------------------------------------------------------------------------- /codebookd.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* codebook/dlsp1.txt */ 11 | static const float codes0[] = { 12 | 25, 13 | 50, 14 | 75, 15 | 100, 16 | 125, 17 | 150, 18 | 175, 19 | 200, 20 | 225, 21 | 250, 22 | 275, 23 | 300, 24 | 325, 25 | 350, 26 | 375, 27 | 400, 28 | 425, 29 | 450, 30 | 475, 31 | 500, 32 | 525, 33 | 550, 34 | 575, 35 | 600, 36 | 625, 37 | 650, 38 | 675, 39 | 700, 40 | 725, 41 | 750, 42 | 775, 43 | 800 44 | }; 45 | /* codebook/dlsp2.txt */ 46 | static const float codes1[] = { 47 | 25, 48 | 50, 49 | 75, 50 | 100, 51 | 125, 52 | 150, 53 | 175, 54 | 200, 55 | 225, 56 | 250, 57 | 275, 58 | 300, 59 | 325, 60 | 350, 61 | 375, 62 | 400, 63 | 425, 64 | 450, 65 | 475, 66 | 500, 67 | 525, 68 | 550, 69 | 575, 70 | 600, 71 | 625, 72 | 650, 73 | 675, 74 | 700, 75 | 725, 76 | 750, 77 | 775, 78 | 800 79 | }; 80 | /* codebook/dlsp3.txt */ 81 | static const float codes2[] = { 82 | 25, 83 | 50, 84 | 75, 85 | 100, 86 | 125, 87 | 150, 88 | 175, 89 | 200, 90 | 225, 91 | 250, 92 | 275, 93 | 300, 94 | 325, 95 | 350, 96 | 375, 97 | 400, 98 | 425, 99 | 450, 100 | 475, 101 | 500, 102 | 525, 103 | 550, 104 | 575, 105 | 600, 106 | 625, 107 | 650, 108 | 675, 109 | 700, 110 | 725, 111 | 750, 112 | 775, 113 | 800 114 | }; 115 | /* codebook/dlsp4.txt */ 116 | static const float codes3[] = { 117 | 25, 118 | 50, 119 | 75, 120 | 100, 121 | 125, 122 | 150, 123 | 175, 124 | 200, 125 | 250, 126 | 300, 127 | 350, 128 | 400, 129 | 450, 130 | 500, 131 | 550, 132 | 600, 133 | 650, 134 | 700, 135 | 750, 136 | 800, 137 | 850, 138 | 900, 139 | 950, 140 | 1000, 141 | 1050, 142 | 1100, 143 | 1150, 144 | 1200, 145 | 1250, 146 | 1300, 147 | 1350, 148 | 1400 149 | }; 150 | /* codebook/dlsp5.txt */ 151 | static const float codes4[] = { 152 | 25, 153 | 50, 154 | 75, 155 | 100, 156 | 125, 157 | 150, 158 | 175, 159 | 200, 160 | 250, 161 | 300, 162 | 350, 163 | 400, 164 | 450, 165 | 500, 166 | 550, 167 | 600, 168 | 650, 169 | 700, 170 | 750, 171 | 800, 172 | 850, 173 | 900, 174 | 950, 175 | 1000, 176 | 1050, 177 | 1100, 178 | 1150, 179 | 1200, 180 | 1250, 181 | 1300, 182 | 1350, 183 | 1400 184 | }; 185 | /* codebook/dlsp6.txt */ 186 | static const float codes5[] = { 187 | 25, 188 | 50, 189 | 75, 190 | 100, 191 | 125, 192 | 150, 193 | 175, 194 | 200, 195 | 250, 196 | 300, 197 | 350, 198 | 400, 199 | 450, 200 | 500, 201 | 550, 202 | 600, 203 | 650, 204 | 700, 205 | 750, 206 | 800, 207 | 850, 208 | 900, 209 | 950, 210 | 1000, 211 | 1050, 212 | 1100, 213 | 1150, 214 | 1200, 215 | 1250, 216 | 1300, 217 | 1350, 218 | 1400 219 | }; 220 | /* codebook/dlsp7.txt */ 221 | static const float codes6[] = { 222 | 25, 223 | 50, 224 | 75, 225 | 100, 226 | 125, 227 | 150, 228 | 175, 229 | 200, 230 | 225, 231 | 250, 232 | 275, 233 | 300, 234 | 325, 235 | 350, 236 | 375, 237 | 400, 238 | 425, 239 | 450, 240 | 475, 241 | 500, 242 | 525, 243 | 550, 244 | 575, 245 | 600, 246 | 625, 247 | 650, 248 | 675, 249 | 700, 250 | 725, 251 | 750, 252 | 775, 253 | 800 254 | }; 255 | /* codebook/dlsp8.txt */ 256 | static const float codes7[] = { 257 | 25, 258 | 50, 259 | 75, 260 | 100, 261 | 125, 262 | 150, 263 | 175, 264 | 200, 265 | 225, 266 | 250, 267 | 275, 268 | 300, 269 | 325, 270 | 350, 271 | 375, 272 | 400, 273 | 425, 274 | 450, 275 | 475, 276 | 500, 277 | 525, 278 | 550, 279 | 575, 280 | 600, 281 | 625, 282 | 650, 283 | 675, 284 | 700, 285 | 725, 286 | 750, 287 | 775, 288 | 800 289 | }; 290 | /* codebook/dlsp9.txt */ 291 | static const float codes8[] = { 292 | 25, 293 | 50, 294 | 75, 295 | 100, 296 | 125, 297 | 150, 298 | 175, 299 | 200, 300 | 225, 301 | 250, 302 | 275, 303 | 300, 304 | 325, 305 | 350, 306 | 375, 307 | 400, 308 | 425, 309 | 450, 310 | 475, 311 | 500, 312 | 525, 313 | 550, 314 | 575, 315 | 600, 316 | 625, 317 | 650, 318 | 675, 319 | 700, 320 | 725, 321 | 750, 322 | 775, 323 | 800 324 | }; 325 | /* codebook/dlsp10.txt */ 326 | static const float codes9[] = { 327 | 25, 328 | 50, 329 | 75, 330 | 100, 331 | 125, 332 | 150, 333 | 175, 334 | 200, 335 | 225, 336 | 250, 337 | 275, 338 | 300, 339 | 325, 340 | 350, 341 | 375, 342 | 400, 343 | 425, 344 | 450, 345 | 475, 346 | 500, 347 | 525, 348 | 550, 349 | 575, 350 | 600, 351 | 625, 352 | 650, 353 | 675, 354 | 700, 355 | 725, 356 | 750, 357 | 775, 358 | 800 359 | }; 360 | 361 | const struct lsp_codebook lsp_cbd[] = { 362 | /* codebook/dlsp1.txt */ 363 | { 364 | 1, 365 | 5, 366 | 32, 367 | codes0 368 | }, 369 | /* codebook/dlsp2.txt */ 370 | { 371 | 1, 372 | 5, 373 | 32, 374 | codes1 375 | }, 376 | /* codebook/dlsp3.txt */ 377 | { 378 | 1, 379 | 5, 380 | 32, 381 | codes2 382 | }, 383 | /* codebook/dlsp4.txt */ 384 | { 385 | 1, 386 | 5, 387 | 32, 388 | codes3 389 | }, 390 | /* codebook/dlsp5.txt */ 391 | { 392 | 1, 393 | 5, 394 | 32, 395 | codes4 396 | }, 397 | /* codebook/dlsp6.txt */ 398 | { 399 | 1, 400 | 5, 401 | 32, 402 | codes5 403 | }, 404 | /* codebook/dlsp7.txt */ 405 | { 406 | 1, 407 | 5, 408 | 32, 409 | codes6 410 | }, 411 | /* codebook/dlsp8.txt */ 412 | { 413 | 1, 414 | 5, 415 | 32, 416 | codes7 417 | }, 418 | /* codebook/dlsp9.txt */ 419 | { 420 | 1, 421 | 5, 422 | 32, 423 | codes8 424 | }, 425 | /* codebook/dlsp10.txt */ 426 | { 427 | 1, 428 | 5, 429 | 32, 430 | codes9 431 | }, 432 | { 0, 0, 0, 0 } 433 | }; 434 | -------------------------------------------------------------------------------- /codebookdt.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* codebook/lspdt1.txt */ 11 | static const float codes0[] = { 12 | -75, 13 | -50, 14 | -25, 15 | 0, 16 | 25, 17 | 50, 18 | 75, 19 | 100 20 | }; 21 | /* codebook/lspdt2.txt */ 22 | static const float codes1[] = { 23 | -75, 24 | -50, 25 | -25, 26 | 0, 27 | 25, 28 | 50, 29 | 75, 30 | 100 31 | }; 32 | /* codebook/lspdt3.txt */ 33 | static const float codes2[] = { 34 | -50, 35 | 0, 36 | 50, 37 | 100 38 | }; 39 | /* codebook/lspdt4.txt */ 40 | static const float codes3[] = { 41 | -50, 42 | 0, 43 | 50, 44 | 100 45 | }; 46 | /* codebook/lspdt5.txt */ 47 | static const float codes4[] = { 48 | -50, 49 | 0, 50 | 50, 51 | 100 52 | }; 53 | /* codebook/lspdt6.txt */ 54 | static const float codes5[] = { 55 | -50, 56 | 0, 57 | 50, 58 | 100 59 | }; 60 | /* codebook/lspdt7.txt */ 61 | static const float codes6[] = { 62 | -50, 63 | 50 64 | }; 65 | /* codebook/lspdt8.txt */ 66 | static const float codes7[] = { 67 | -50, 68 | 50 69 | }; 70 | /* codebook/lspdt9.txt */ 71 | static const float codes8[] = { 72 | -50, 73 | 50 74 | }; 75 | /* codebook/lspdt10.txt */ 76 | static const float codes9[] = { 77 | -50, 78 | 50 79 | }; 80 | 81 | const struct lsp_codebook lsp_cbdt[] = { 82 | /* codebook/lspdt1.txt */ 83 | { 84 | 1, 85 | 3, 86 | 8, 87 | codes0 88 | }, 89 | /* codebook/lspdt2.txt */ 90 | { 91 | 1, 92 | 3, 93 | 8, 94 | codes1 95 | }, 96 | /* codebook/lspdt3.txt */ 97 | { 98 | 1, 99 | 2, 100 | 4, 101 | codes2 102 | }, 103 | /* codebook/lspdt4.txt */ 104 | { 105 | 1, 106 | 2, 107 | 4, 108 | codes3 109 | }, 110 | /* codebook/lspdt5.txt */ 111 | { 112 | 1, 113 | 2, 114 | 4, 115 | codes4 116 | }, 117 | /* codebook/lspdt6.txt */ 118 | { 119 | 1, 120 | 2, 121 | 4, 122 | codes5 123 | }, 124 | /* codebook/lspdt7.txt */ 125 | { 126 | 1, 127 | 1, 128 | 2, 129 | codes6 130 | }, 131 | /* codebook/lspdt8.txt */ 132 | { 133 | 1, 134 | 1, 135 | 2, 136 | codes7 137 | }, 138 | /* codebook/lspdt9.txt */ 139 | { 140 | 1, 141 | 1, 142 | 2, 143 | codes8 144 | }, 145 | /* codebook/lspdt10.txt */ 146 | { 147 | 1, 148 | 1, 149 | 2, 150 | codes9 151 | }, 152 | { 0, 0, 0, 0 } 153 | }; 154 | -------------------------------------------------------------------------------- /codebookge.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* codebook/gecb.txt */ 11 | static const float codes0[] = { 12 | 2.71, 12.0184, 13 | 0.04675, -2.73881, 14 | 0.120993, 8.38895, 15 | -1.58028, -0.892307, 16 | 1.19307, -1.91561, 17 | 0.187101, -3.27679, 18 | 0.332251, -7.66455, 19 | -1.47944, 31.2461, 20 | 1.52761, 27.7095, 21 | -0.524379, 5.25012, 22 | 0.55333, 7.4388, 23 | -0.843451, -1.95299, 24 | 2.26389, 8.61029, 25 | 0.143143, 2.36549, 26 | 0.616506, 1.28427, 27 | -1.71133, 22.0967, 28 | 1.00813, 17.3965, 29 | -0.106718, 1.41891, 30 | -0.136246, 14.2736, 31 | -1.70909, -20.5319, 32 | 1.65787, -3.39107, 33 | 0.138049, -4.95785, 34 | 0.536729, -1.94375, 35 | 0.196307, 36.8519, 36 | 1.27248, 22.5565, 37 | -0.670219, -1.90604, 38 | 0.382092, 6.40113, 39 | -0.756911, -4.90102, 40 | 1.82931, 4.6138, 41 | 0.318794, 0.73683, 42 | 0.612815, -2.07505, 43 | -0.410151, 24.7871, 44 | 1.77602, 13.1909, 45 | 0.106457, -0.104492, 46 | 0.192206, 10.1838, 47 | -1.82442, -7.71565, 48 | 0.931346, 4.34835, 49 | 0.308813, -4.086, 50 | 0.397143, -11.8089, 51 | -0.048715, 41.2273, 52 | 0.877342, 35.8503, 53 | -0.759794, 0.476634, 54 | 0.978593, 7.67467, 55 | -1.19506, 3.03883, 56 | 2.63989, -3.41106, 57 | 0.191127, 3.60351, 58 | 0.402932, 1.0843, 59 | -2.15202, 18.1076, 60 | 1.5468, 8.32271, 61 | -0.143089, -4.07592, 62 | -0.150142, 5.86674, 63 | -1.40844, -3.2507, 64 | 1.56615, -10.4132, 65 | 0.178171, -10.2267, 66 | 0.362164, -0.028556, 67 | -0.070125, 24.3907, 68 | 0.594752, 17.4828, 69 | -0.28698, -6.90407, 70 | 0.464818, 10.2055, 71 | -1.00684, -14.3572, 72 | 2.32957, -3.69161, 73 | 0.335745, 2.40714, 74 | 1.01966, -3.15565, 75 | -1.25945, 7.9919, 76 | 2.38369, 19.6806, 77 | -0.094947, -2.41374, 78 | 0.20933, 6.66477, 79 | -2.22103, 1.37986, 80 | 1.29239, 2.04633, 81 | 0.243626, -0.890741, 82 | 0.428773, -7.19366, 83 | -1.11374, 41.3414, 84 | 2.6098, 31.1405, 85 | -0.446468, 2.53419, 86 | 0.490104, 4.62757, 87 | -1.11723, -3.24174, 88 | 1.79156, 8.41493, 89 | 0.156012, 0.183336, 90 | 0.532447, 3.15455, 91 | -0.764484, 18.514, 92 | 0.952395, 11.7713, 93 | -0.332567, 0.346987, 94 | 0.202165, 14.7168, 95 | -2.12924, -15.559, 96 | 1.35358, -1.92679, 97 | -0.010963, -16.3364, 98 | 0.399053, -2.79057, 99 | 0.750657, 31.1483, 100 | 0.655743, 24.4819, 101 | -0.45321, -0.735879, 102 | 0.2869, 6.5467, 103 | -0.715673, -12.3578, 104 | 1.54849, 3.87217, 105 | 0.271874, 0.802339, 106 | 0.502073, -4.85485, 107 | -0.497037, 17.7619, 108 | 1.19116, 13.9544, 109 | 0.01563, 1.33157, 110 | 0.341867, 8.93537, 111 | -2.31601, -5.39506, 112 | 0.75861, 1.9645, 113 | 0.24132, -3.23769, 114 | 0.267151, -11.2344, 115 | -0.273126, 32.6248, 116 | 1.75352, 40.432, 117 | -0.784011, 3.04576, 118 | 0.705987, 5.66118, 119 | -1.3864, 1.35356, 120 | 2.37646, 1.67485, 121 | 0.242973, 4.73218, 122 | 0.491227, 0.354061, 123 | -1.60676, 8.65895, 124 | 1.16711, 5.9871, 125 | -0.137601, -12.0417, 126 | -0.251375, 10.3972, 127 | -1.43151, -8.90411, 128 | 0.98828, -13.209, 129 | 0.261484, -6.35497, 130 | 0.395932, -0.702529, 131 | 0.283704, 26.8996, 132 | 0.420959, 15.4418, 133 | -0.355804, -13.7278, 134 | 0.527372, 12.3985, 135 | -1.16956, -15.9985, 136 | 1.90669, -5.81605, 137 | 0.354492, 3.85157, 138 | 0.82576, -4.16264, 139 | -0.49019, 13.0572, 140 | 2.25577, 13.5264, 141 | -0.004956, -3.23713, 142 | 0.026709, 7.86645, 143 | -1.81037, -0.451183, 144 | 1.08383, -0.18362, 145 | 0.135836, -2.26658, 146 | 0.375812, -5.51225, 147 | -1.96644, 38.6829, 148 | 1.97799, 24.5655, 149 | -0.704656, 6.35881, 150 | 0.480786, 7.05175, 151 | -0.976417, -2.42273, 152 | 2.50215, 6.75935, 153 | 0.083588, 3.2588, 154 | 0.543629, 0.910013, 155 | -1.23196, 23.0915, 156 | 0.785492, 14.807, 157 | -0.213554, 1.688, 158 | 0.004748, 18.1718, 159 | -1.54719, -16.1168, 160 | 1.50104, -3.28114, 161 | 0.080133, -4.63472, 162 | 0.476592, -2.18093, 163 | 0.44247, 40.304, 164 | 1.07277, 27.592, 165 | -0.594738, -4.16681, 166 | 0.42248, 7.61609, 167 | -0.927521, -7.27441, 168 | 1.99162, 1.29636, 169 | 0.291307, 2.39878, 170 | 0.721081, -1.95062, 171 | -0.804256, 24.9295, 172 | 1.64839, 19.1197, 173 | 0.060852, -0.590639, 174 | 0.266085, 9.10325, 175 | -1.9574, -2.88461, 176 | 1.11693, 2.6724, 177 | 0.35458, -2.74854, 178 | 0.330733, -14.1561, 179 | -0.527851, 39.5756, 180 | 0.991152, 43.195, 181 | -0.589619, 1.26919, 182 | 0.787401, 8.73071, 183 | -1.0138, 1.02507, 184 | 2.8254, 1.89538, 185 | 0.24089, 2.74557, 186 | 0.427195, 2.54446, 187 | -1.95311, 12.244, 188 | 1.44862, 12.0607, 189 | -0.210492, -3.37906, 190 | -0.056713, 10.204, 191 | -1.65237, -5.10274, 192 | 1.29475, -12.2708, 193 | 0.111608, -8.67592, 194 | 0.326634, -1.16763, 195 | 0.021781, 31.1258, 196 | 0.455335, 21.4684, 197 | -0.37544, -3.37121, 198 | 0.39362, 11.302, 199 | -0.851456, -19.4149, 200 | 2.10703, -2.22886, 201 | 0.373233, 1.92406, 202 | 0.884438, -1.72058, 203 | -0.975127, 9.84013, 204 | 2.0033, 17.3954, 205 | -0.036915, -1.11137, 206 | 0.148456, 5.39997, 207 | -1.91441, 4.77382, 208 | 1.44791, 0.537122, 209 | 0.194979, -1.03818, 210 | 0.495771, -9.95502, 211 | -1.05899, 32.9471, 212 | 2.01122, 32.4544, 213 | -0.30965, 4.71911, 214 | 0.436082, 4.63552, 215 | -1.23711, -1.25428, 216 | 2.02274, 9.42834, 217 | 0.190342, 1.46077, 218 | 0.479017, 2.48479, 219 | -1.07848, 16.2217, 220 | 1.20764, 9.65421, 221 | -0.258087, -1.67236, 222 | 0.071852, 13.416, 223 | -1.87723, -16.072, 224 | 1.28957, -4.87118, 225 | 0.067713, -13.4427, 226 | 0.435551, -4.1655, 227 | 0.46614, 30.5895, 228 | 0.904895, 21.598, 229 | -0.518369, -2.53205, 230 | 0.337363, 5.63726, 231 | -0.554975, -17.4005, 232 | 1.69188, 1.14574, 233 | 0.227934, 0.889297, 234 | 0.587303, -5.72973, 235 | -0.262133, 18.6666, 236 | 1.39505, 17.0029, 237 | -0.01909, 4.30838, 238 | 0.304235, 12.6699, 239 | -2.07406, -6.46084, 240 | 0.920546, 1.21296, 241 | 0.284927, -1.78547, 242 | 0.209724, -16.024, 243 | -0.636067, 31.5768, 244 | 1.34989, 34.6775, 245 | -0.971625, 5.30086, 246 | 0.590249, 4.44971, 247 | -1.56787, 3.60239, 248 | 2.1455, 4.51666, 249 | 0.296022, 4.12017, 250 | 0.445299, 0.868772, 251 | -1.44193, 14.1284, 252 | 1.35575, 6.0074, 253 | -0.012814, -7.49657, 254 | -0.43, 8.50012, 255 | -1.20469, -7.11326, 256 | 1.10102, -6.83682, 257 | 0.196463, -6.234, 258 | 0.436747, -1.12979, 259 | 0.141052, 22.8549, 260 | 0.290821, 18.8114, 261 | -0.529536, -7.73251, 262 | 0.63428, 10.7898, 263 | -1.33472, -20.3258, 264 | 1.81564, -1.90332, 265 | 0.394778, 3.79758, 266 | 0.732682, -8.18382, 267 | -0.741244, 11.7683 268 | }; 269 | 270 | const struct lsp_codebook ge_cb[] = { 271 | /* codebook/gecb.txt */ 272 | { 273 | 2, 274 | 8, 275 | 256, 276 | codes0 277 | }, 278 | { 0, 0, 0, 0 } 279 | }; 280 | -------------------------------------------------------------------------------- /codebookmel.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel1.txt */ 11 | static const float codes0[] = { 12 | 550, 13 | 600, 14 | 650, 15 | 700, 16 | 750, 17 | 800, 18 | 850, 19 | 900 20 | }; 21 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel2.txt */ 22 | static const float codes1[] = { 23 | 50, 24 | 100, 25 | 200, 26 | 300 27 | }; 28 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel3.txt */ 29 | static const float codes2[] = { 30 | 800, 31 | 850, 32 | 900, 33 | 950, 34 | 1000, 35 | 1050, 36 | 1100, 37 | 1150, 38 | 1200, 39 | 1250, 40 | 1300, 41 | 1350, 42 | 1400, 43 | 1450, 44 | 1500, 45 | 1650 46 | }; 47 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel4.txt */ 48 | static const float codes3[] = { 49 | 25, 50 | 50, 51 | 75, 52 | 100, 53 | 125, 54 | 150, 55 | 175, 56 | 250 57 | }; 58 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel5.txt */ 59 | static const float codes4[] = { 60 | 1350, 61 | 1400, 62 | 1450, 63 | 1500, 64 | 1550, 65 | 1600, 66 | 1650, 67 | 1700 68 | }; 69 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel6.txt */ 70 | static const float codes5[] = { 71 | 25, 72 | 50, 73 | 100, 74 | 150 75 | }; 76 | 77 | const struct lsp_codebook mel_cb[] = { 78 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel1.txt */ 79 | { 80 | 1, 81 | 3, 82 | 8, 83 | codes0 84 | }, 85 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel2.txt */ 86 | { 87 | 1, 88 | 2, 89 | 4, 90 | codes1 91 | }, 92 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel3.txt */ 93 | { 94 | 1, 95 | 4, 96 | 16, 97 | codes2 98 | }, 99 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel4.txt */ 100 | { 101 | 1, 102 | 3, 103 | 8, 104 | codes3 105 | }, 106 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel5.txt */ 107 | { 108 | 1, 109 | 3, 110 | 8, 111 | codes4 112 | }, 113 | /* /builddir/build/BUILD/codec2-0.8.1/src/codebook/mel6.txt */ 114 | { 115 | 1, 116 | 2, 117 | 4, 118 | codes5 119 | }, 120 | { 0, 0, 0, 0 } 121 | }; 122 | -------------------------------------------------------------------------------- /codebooknewamp1_energy.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* /home/david/codec2-dev/src/codebook/newamp1_energy_q.txt */ 11 | static const float codes0[] = { 12 | 10, 13 | 12.5, 14 | 15, 15 | 17.5, 16 | 20, 17 | 22.5, 18 | 25, 19 | 27.5, 20 | 30, 21 | 32.5, 22 | 35, 23 | 37.5, 24 | 40, 25 | 42.5, 26 | 45, 27 | 47.5 28 | }; 29 | 30 | const struct lsp_codebook newamp1_energy_cb[] = { 31 | /* /home/david/codec2-dev/src/codebook/newamp1_energy_q.txt */ 32 | { 33 | 1, 34 | 4, 35 | 16, 36 | codes0 37 | }, 38 | { 0, 0, 0, 0 } 39 | }; 40 | -------------------------------------------------------------------------------- /codebookres.c: -------------------------------------------------------------------------------- 1 | /* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */ 2 | 3 | /* 4 | * This intermediary file and the files that used to create it are under 5 | * The LGPL. See the file COPYING. 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | /* ../src/codebook/lspres_centre1.txt */ 11 | static const float codes0[] = { 12 | 300, 13 | 350, 14 | 400, 15 | 450, 16 | 500, 17 | 550, 18 | 600, 19 | 650 20 | }; 21 | /* ../src/codebook/lspres_bw1.txt */ 22 | static const float codes1[] = { 23 | 35, 24 | 80, 25 | 140, 26 | 250 27 | }; 28 | /* ../src/codebook/lsp3.txt */ 29 | static const float codes2[] = { 30 | 500, 31 | 550, 32 | 600, 33 | 650, 34 | 700, 35 | 750, 36 | 800, 37 | 850, 38 | 900, 39 | 950, 40 | 1000, 41 | 1050, 42 | 1100, 43 | 1150, 44 | 1200, 45 | 1250 46 | }; 47 | /* ../src/codebook/lsp4.txt */ 48 | static const float codes3[] = { 49 | 700, 50 | 800, 51 | 900, 52 | 1000, 53 | 1100, 54 | 1200, 55 | 1300, 56 | 1400, 57 | 1500, 58 | 1600, 59 | 1700, 60 | 1800, 61 | 1900, 62 | 2000, 63 | 2100, 64 | 2200 65 | }; 66 | 67 | const struct lsp_codebook lsp_cbres[] = { 68 | /* ../src/codebook/lspres_centre1.txt */ 69 | { 70 | 1, 71 | 3, 72 | 8, 73 | codes0 74 | }, 75 | /* ../src/codebook/lspres_bw1.txt */ 76 | { 77 | 1, 78 | 2, 79 | 4, 80 | codes1 81 | }, 82 | /* ../src/codebook/lsp3.txt */ 83 | { 84 | 1, 85 | 4, 86 | 16, 87 | codes2 88 | }, 89 | /* ../src/codebook/lsp4.txt */ 90 | { 91 | 1, 92 | 4, 93 | 16, 94 | codes3 95 | }, 96 | { 0, 0, 0, 0 } 97 | }; 98 | -------------------------------------------------------------------------------- /codec2.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: codec2.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 21 August 2010 6 | 7 | Codec 2 fully quantised encoder and decoder functions. If you want use 8 | Codec 2, these are the functions you need to call. 9 | 10 | \*---------------------------------------------------------------------------*/ 11 | 12 | /* 13 | Copyright (C) 2010 David Rowe 14 | 15 | All rights reserved. 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU Lesser General Public License version 2.1, as 19 | published by the Free Software Foundation. This program is 20 | distributed in the hope that it will be useful, but WITHOUT ANY 21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 22 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23 | License for more details. 24 | 25 | You should have received a copy of the GNU Lesser General Public License 26 | along with this program; if not, see . 27 | */ 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #ifndef __CODEC2__ 34 | #define __CODEC2__ 35 | 36 | #include "version.h" 37 | 38 | #define CODEC2_MODE_3200 0 39 | #define CODEC2_MODE_2400 1 40 | #define CODEC2_MODE_1600 2 41 | #define CODEC2_MODE_1400 3 42 | #define CODEC2_MODE_1300 4 43 | #define CODEC2_MODE_1200 5 44 | #define CODEC2_MODE_700 6 45 | #define CODEC2_MODE_700B 7 46 | #define CODEC2_MODE_700C 8 47 | #define CODEC2_MODE_WB 9 48 | 49 | struct CODEC2; 50 | 51 | struct CODEC2 * codec2_create(int mode); 52 | void codec2_destroy(struct CODEC2 *codec2_state); 53 | void codec2_encode(struct CODEC2 *codec2_state, unsigned char * bits, short speech_in[]); 54 | void codec2_decode(struct CODEC2 *codec2_state, short speech_out[], const unsigned char *bits); 55 | void codec2_decode_ber(struct CODEC2 *codec2_state, short speech_out[], const unsigned char *bits, float ber_est); 56 | int codec2_samples_per_frame(struct CODEC2 *codec2_state); 57 | int codec2_bits_per_frame(struct CODEC2 *codec2_state); 58 | 59 | void codec2_set_lpc_post_filter(struct CODEC2 *codec2_state, int enable, int bass_boost, float beta, float gamma); 60 | int codec2_get_spare_bit_index(struct CODEC2 *codec2_state); 61 | int codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]); 62 | void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray); 63 | void codec2_set_softdec(struct CODEC2 *c2, float *softdec); 64 | float codec2_get_energy(struct CODEC2 *codec2_state, const unsigned char *bits); 65 | 66 | 67 | #endif 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | -------------------------------------------------------------------------------- /codec2_fdmdv.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: codec2_fdmdv.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: April 14 2012 6 | 7 | A 1400 bit/s (nominal) Frequency Division Multiplexed Digital Voice 8 | (FDMDV) modem. Used for digital audio over HF SSB. See 9 | README_fdmdv.txt for more information, and fdmdv_mod.c and 10 | fdmdv_demod.c for example usage. 11 | 12 | The name codec2_fdmdv.h is used to make it unique when "make 13 | installed". 14 | 15 | References: 16 | 17 | [1] http://n1su.com/fdmdv/FDMDV_Docs_Rel_1_4b.pdf 18 | 19 | \*---------------------------------------------------------------------------*/ 20 | 21 | /* 22 | Copyright (C) 2012 David Rowe 23 | 24 | All rights reserved. 25 | 26 | This program is free software; you can redistribute it and/or modify 27 | it under the terms of the GNU Lesser General Public License version 2.1, as 28 | published by the Free Software Foundation. This program is 29 | distributed in the hope that it will be useful, but WITHOUT ANY 30 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 31 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 32 | License for more details. 33 | 34 | You should have received a copy of the GNU Lesser General Public License 35 | along with this program; if not, see . 36 | */ 37 | 38 | #ifndef __FDMDV__ 39 | #define __FDMDV__ 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* set up the calling convention for DLL function import/export for 46 | WIN32 cross compiling */ 47 | 48 | #ifdef __CODEC2_WIN32__ 49 | #ifdef __CODEC2_BUILDING_DLL__ 50 | #define CODEC2_WIN32SUPPORT __declspec(dllexport) __stdcall 51 | #else 52 | #define CODEC2_WIN32SUPPORT __declspec(dllimport) __stdcall 53 | #endif 54 | #else 55 | #define CODEC2_WIN32SUPPORT 56 | #endif 57 | 58 | #include "comp.h" 59 | #include "modem_stats.h" 60 | 61 | #define FDMDV_NC 14 /* default number of data carriers */ 62 | #define FDMDV_NC_MAX 20 /* maximum number of data carriers */ 63 | #define FDMDV_BITS_PER_FRAME 28 /* 20ms frames, for nominal 1400 bit/s */ 64 | #define FDMDV_NOM_SAMPLES_PER_FRAME 160 /* modulator output samples/frame and nominal demod samples/frame */ 65 | /* at 8000 Hz sample rate */ 66 | #define FDMDV_MAX_SAMPLES_PER_FRAME 200 /* max demod samples/frame, use this to allocate storage */ 67 | #define FDMDV_SCALE 1000 /* suggested scaling for 16 bit shorts */ 68 | #define FDMDV_FCENTRE 1500 /* Centre frequency, Nc/2 carriers below this, Nc/2 carriers above (Hz) */ 69 | 70 | /* 8 to 48 kHz sample rate conversion */ 71 | 72 | #define FDMDV_OS 2 /* oversampling rate */ 73 | #define FDMDV_OS_TAPS_16K 48 /* number of OS filter taps at 16kHz */ 74 | #define FDMDV_OS_TAPS_8K (FDMDV_OS_TAPS_16K/FDMDV_OS) /* number of OS filter taps at 8kHz */ 75 | 76 | /* FDMDV states and stats structures */ 77 | 78 | struct FDMDV; 79 | 80 | struct FDMDV * fdmdv_create(int Nc); 81 | void fdmdv_destroy(struct FDMDV *fdmdv_state); 82 | void fdmdv_use_old_qpsk_mapping(struct FDMDV *fdmdv_state); 83 | int fdmdv_bits_per_frame(struct FDMDV *fdmdv_state); 84 | float fdmdv_get_fsep(struct FDMDV *fdmdv_state); 85 | void fdmdv_set_fsep(struct FDMDV *fdmdv_state, float fsep); 86 | 87 | void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[], int *sync_bit); 88 | void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin); 89 | 90 | void fdmdv_get_test_bits(struct FDMDV *fdmdv_state, int tx_bits[]); 91 | int fdmdv_error_pattern_size(struct FDMDV *fdmdv_state); 92 | void fdmdv_put_test_bits(struct FDMDV *f, int *sync, short error_pattern[], int *bit_errors, int *ntest_bits, int rx_bits[]); 93 | 94 | void fdmdv_get_demod_stats(struct FDMDV *fdmdv_state, struct MODEM_STATS *stats); 95 | 96 | void fdmdv_8_to_16(float out16k[], float in8k[], int n); 97 | void fdmdv_8_to_16_short(short out16k[], short in8k[], int n); 98 | void fdmdv_16_to_8(float out8k[], float in16k[], int n); 99 | void fdmdv_16_to_8_short(short out8k[], short in16k[], int n); 100 | 101 | void fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, COMP *foff_phase_rect, int nin); 102 | 103 | /* debug/development function(s) */ 104 | 105 | void fdmdv_dump_osc_mags(struct FDMDV *f); 106 | void fdmdv_simulate_channel(float *sig_pwr_av, COMP samples[], int nin, float target_snr); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /codec2_fft.c: -------------------------------------------------------------------------------- 1 | /* 2 | * codec2_fft.c 3 | * 4 | * Created on: 24.09.2016 5 | * Author: danilo 6 | */ 7 | 8 | #include "codec2_fft.h" 9 | #ifdef USE_KISS_FFT 10 | #include "_kiss_fft_guts.h" 11 | 12 | #else 13 | #if 0 14 | // caching constants in RAM did not seem to have an effect on performance 15 | // TODO: Decide what to with this code 16 | #define FFT_INIT_CACHE_SIZE 4 17 | const arm_cfft_instance_f32* fft_init_cache[FFT_INIT_CACHE_SIZE]; 18 | 19 | static const arm_cfft_instance_f32* arm_fft_instance2ram(const arm_cfft_instance_f32* in) 20 | { 21 | 22 | arm_cfft_instance_f32* out = malloc(sizeof(arm_cfft_instance_f32)); 23 | 24 | if (out) { 25 | memcpy(out,in,sizeof(arm_cfft_instance_f32)); 26 | out->pBitRevTable = malloc(out->bitRevLength * sizeof(uint16_t)); 27 | out->pTwiddle = malloc(out->fftLen * sizeof(float32_t)); 28 | memcpy((void*)out->pBitRevTable,in->pBitRevTable,out->bitRevLength * sizeof(uint16_t)); 29 | memcpy((void*)out->pTwiddle,in->pTwiddle,out->fftLen * sizeof(float32_t)); 30 | } 31 | return out; 32 | } 33 | 34 | 35 | static const arm_cfft_instance_f32* arm_fft_cache_get(const arm_cfft_instance_f32* romfft) 36 | { 37 | const arm_cfft_instance_f32* retval = NULL; 38 | static int used = 0; 39 | for (int i = 0; fft_init_cache[i] != NULL && i < used; i++) 40 | { 41 | if (romfft->fftLen == fft_init_cache[i]->fftLen) 42 | { 43 | retval = fft_init_cache[i]; 44 | break; 45 | } 46 | } 47 | if (retval == NULL && used < FFT_INIT_CACHE_SIZE) 48 | { 49 | retval = arm_fft_instance2ram(romfft); 50 | fft_init_cache[used++] = retval; 51 | } 52 | if (retval == NULL) 53 | { 54 | retval = romfft; 55 | } 56 | return retval; 57 | } 58 | #endif 59 | #endif 60 | 61 | void codec2_fft_free(codec2_fft_cfg cfg) 62 | { 63 | #ifdef USE_KISS_FFT 64 | KISS_FFT_FREE(cfg); 65 | #else 66 | free(cfg); 67 | #endif 68 | } 69 | 70 | codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem) 71 | { 72 | codec2_fft_cfg retval; 73 | #ifdef USE_KISS_FFT 74 | retval = kiss_fft_alloc(nfft, inverse_fft, mem, lenmem); 75 | #else 76 | retval = malloc(sizeof(codec2_fft_struct)); 77 | retval->inverse = inverse_fft; 78 | switch(nfft) 79 | { 80 | case 128: 81 | retval->instance = &arm_cfft_sR_f32_len128; 82 | break; 83 | case 256: 84 | retval->instance = &arm_cfft_sR_f32_len256; 85 | break; 86 | case 512: 87 | retval->instance = &arm_cfft_sR_f32_len512; 88 | break; 89 | // case 1024: 90 | // retval->instance = &arm_cfft_sR_f32_len1024; 91 | // break; 92 | default: 93 | abort(); 94 | } 95 | // retval->instance = arm_fft_cache_get(retval->instance); 96 | #endif 97 | return retval; 98 | } 99 | 100 | codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem) 101 | { 102 | codec2_fftr_cfg retval; 103 | #ifdef USE_KISS_FFT 104 | retval = kiss_fftr_alloc(nfft, inverse_fft, mem, lenmem); 105 | #else 106 | retval = malloc(sizeof(codec2_fftr_struct)); 107 | retval->inverse = inverse_fft; 108 | retval->instance = malloc(sizeof(arm_rfft_fast_instance_f32)); 109 | arm_rfft_fast_init_f32(retval->instance,nfft); 110 | // memcpy(&retval->instance->Sint,arm_fft_cache_get(&retval->instance->Sint),sizeof(arm_cfft_instance_f32)); 111 | #endif 112 | return retval; 113 | } 114 | void codec2_fftr_free(codec2_fftr_cfg cfg) 115 | { 116 | #ifdef USE_KISS_FFT 117 | KISS_FFT_FREE(cfg); 118 | #else 119 | free(cfg->instance); 120 | free(cfg); 121 | #endif 122 | } 123 | 124 | // there is a little overhead for inplace kiss_fft but this is 125 | // on the powerful platforms like the Raspberry or even x86 PC based ones 126 | // not noticeable 127 | // the reduced usage of RAM and increased performance on STM32 platforms 128 | // should be worth it. 129 | void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout) 130 | { 131 | 132 | #ifdef USE_KISS_FFT 133 | kiss_fft_cpx in[512]; 134 | // decide whether to use the local stack based buffer for in 135 | // or to allow kiss_fft to allocate RAM 136 | // second part is just to play safe since first method 137 | // is much faster and uses less RAM 138 | if (cfg->nfft <= 512) 139 | { 140 | memcpy(in,inout,cfg->nfft*sizeof(kiss_fft_cpx)); 141 | kiss_fft(cfg, in, (kiss_fft_cpx*)inout); 142 | } 143 | else 144 | { 145 | kiss_fft(cfg, (kiss_fft_cpx*)inout, (kiss_fft_cpx*)inout); 146 | } 147 | #else 148 | arm_cfft_f32(cfg->instance,(float*)inout,cfg->inverse,1); 149 | if (cfg->inverse) 150 | { 151 | arm_scale_f32((float*)inout,cfg->instance->fftLen,(float*)inout,cfg->instance->fftLen*2); 152 | } 153 | 154 | #endif 155 | } 156 | -------------------------------------------------------------------------------- /codec2_fft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * codec2_fft.h 3 | * 4 | * Created on: 17.09.2016 5 | * Author: danilo 6 | */ 7 | 8 | #ifndef DRIVERS_FREEDV_CODEC2_FFT_H_ 9 | #define DRIVERS_FREEDV_CODEC2_FFT_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef ARM_MATH_CM4 18 | #include "stm32f4xx.h" 19 | #include "core_cm4.h" 20 | #include "arm_math.h" 21 | #include "arm_const_structs.h" 22 | #endif 23 | 24 | #include "defines.h" 25 | #include "comp.h" 26 | 27 | #ifndef ARM_MATH_CM4 28 | #define USE_KISS_FFT 29 | #endif 30 | // #define USE_KISS_FFT 31 | 32 | 33 | typedef COMP codec2_fft_cpx; 34 | #include "kiss_fftr.h" 35 | 36 | #ifdef USE_KISS_FFT 37 | #include "kiss_fft.h" 38 | typedef kiss_fftr_cfg codec2_fftr_cfg; 39 | typedef kiss_fft_cfg codec2_fft_cfg; 40 | typedef kiss_fft_scalar codec2_fft_scalar; 41 | #else 42 | typedef float32_t codec2_fft_scalar; 43 | typedef struct { 44 | arm_rfft_fast_instance_f32* instance; 45 | int inverse; 46 | } codec2_fftr_struct; 47 | 48 | typedef codec2_fftr_struct* codec2_fftr_cfg; 49 | 50 | typedef struct { 51 | const arm_cfft_instance_f32* instance; 52 | int inverse; 53 | } codec2_fft_struct; 54 | typedef codec2_fft_struct* codec2_fft_cfg; 55 | #endif 56 | 57 | 58 | 59 | static inline void codec2_fftr(codec2_fftr_cfg cfg, codec2_fft_scalar* in, codec2_fft_cpx* out) 60 | { 61 | 62 | #ifdef USE_KISS_FFT 63 | kiss_fftr(cfg, in, (kiss_fft_cpx*)out); 64 | #else 65 | arm_rfft_fast_f32(cfg->instance,in,(float*)out,cfg->inverse); 66 | out->imag = 0; // remove out[FFT_ENC/2]->real stored in out[0].imag 67 | #endif 68 | } 69 | 70 | static inline void codec2_fftri(codec2_fftr_cfg cfg, codec2_fft_cpx* in, codec2_fft_scalar* out) 71 | { 72 | #ifdef USE_KISS_FFT 73 | kiss_fftri(cfg, (kiss_fft_cpx*)in, out); 74 | #else 75 | arm_rfft_fast_f32(cfg->instance,(float*)in,out,cfg->inverse); 76 | // arm_scale_f32(out,cfg->instance->fftLenRFFT,out,cfg->instance->fftLenRFFT); 77 | #endif 78 | 79 | } 80 | 81 | codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem); 82 | codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem); 83 | void codec2_fft_free(codec2_fft_cfg cfg); 84 | void codec2_fftr_free(codec2_fftr_cfg cfg); 85 | 86 | 87 | static inline void codec2_fft(codec2_fft_cfg cfg, codec2_fft_cpx* in, codec2_fft_cpx* out) 88 | { 89 | 90 | #ifdef USE_KISS_FFT 91 | kiss_fft(cfg, (kiss_fft_cpx*)in, (kiss_fft_cpx*)out); 92 | #else 93 | memcpy(out,in,cfg->instance->fftLen*2*sizeof(float)); 94 | arm_cfft_f32(cfg->instance,(float*)out,cfg->inverse,0); 95 | // TODO: this is not nice, but for now required to keep changes minimal 96 | // however, since main goal is to reduce the memory usage 97 | // we should convert to an in place interface 98 | // on PC like platforms the overhead of using the "inplace" kiss_fft calls 99 | // is neglectable compared to the gain in memory usage on STM32 platforms 100 | if (cfg->inverse) 101 | { 102 | arm_scale_f32((float*)out,cfg->instance->fftLen,(float*)out,cfg->instance->fftLen*2); 103 | } 104 | #endif 105 | } 106 | 107 | void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout); 108 | 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /codec2_internal.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: codec2_internal.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: April 16 2012 6 | 7 | Header file for Codec2 internal states, exposed via this header 8 | file to assist in testing. 9 | 10 | \*---------------------------------------------------------------------------*/ 11 | 12 | /* 13 | Copyright (C) 2012 David Rowe 14 | 15 | All rights reserved. 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU Lesser General Public License version 2.1, as 19 | published by the Free Software Foundation. This program is 20 | distributed in the hope that it will be useful, but WITHOUT ANY 21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 22 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23 | License for more details. 24 | 25 | You should have received a copy of the GNU Lesser General Public License 26 | along with this program; if not, see . 27 | */ 28 | 29 | #ifndef __CODEC2_INTERNAL__ 30 | #define __CODEC2_INTERNAL__ 31 | 32 | #include "codec2_fft.h" 33 | #include "newamp1.h" 34 | 35 | struct CODEC2 { 36 | int mode; 37 | C2CONST c2const; 38 | int Fs; 39 | int n_samp; 40 | int m_pitch; 41 | codec2_fft_cfg fft_fwd_cfg; /* forward FFT config */ 42 | codec2_fftr_cfg fftr_fwd_cfg; /* forward real FFT config */ 43 | float *w; /* [m_pitch] time domain hamming window */ 44 | COMP W[FFT_ENC]; /* DFT of w[] */ 45 | float *Pn; /* [2*n_samp] trapezoidal synthesis window */ 46 | float *bpf_buf; /* buffer for band pass filter */ 47 | float *Sn; /* [m_pitch] input speech */ 48 | float hpf_states[2]; /* high pass filter states */ 49 | void *nlp; /* pitch predictor states */ 50 | int gray; /* non-zero for gray encoding */ 51 | 52 | codec2_fftr_cfg fftr_inv_cfg; /* inverse FFT config */ 53 | float *Sn_; /* [2*n_samp] synthesised output speech */ 54 | float ex_phase; /* excitation model phase track */ 55 | float bg_est; /* background noise estimate for post filter */ 56 | float prev_f0_enc; /* previous frame's f0 estimate */ 57 | MODEL prev_model_dec; /* previous frame's model parameters */ 58 | float prev_lsps_dec[LPC_ORD]; /* previous frame's LSPs */ 59 | float prev_e_dec; /* previous frame's LPC energy */ 60 | 61 | int lpc_pf; /* LPC post filter on */ 62 | int bass_boost; /* LPC post filter bass boost */ 63 | float beta; /* LPC post filter parameters */ 64 | float gamma; 65 | 66 | float xq_enc[2]; /* joint pitch and energy VQ states */ 67 | float xq_dec[2]; 68 | 69 | int smoothing; /* enable smoothing for channels with errors */ 70 | float *softdec; /* optional soft decn bits from demod */ 71 | 72 | /* newamp1 states */ 73 | 74 | float rate_K_sample_freqs_kHz[NEWAMP1_K]; 75 | float prev_rate_K_vec_[NEWAMP1_K]; 76 | float Wo_left; 77 | int voicing_left; 78 | codec2_fft_cfg phase_fft_fwd_cfg; 79 | codec2_fft_cfg phase_fft_inv_cfg; 80 | }; 81 | 82 | // test and debug 83 | void analyse_one_frame(struct CODEC2 *c2, MODEL *model, short speech[]); 84 | void synthesise_one_frame(struct CODEC2 *c2, short speech[], MODEL *model, 85 | COMP Aw[], float gain); 86 | #endif 87 | -------------------------------------------------------------------------------- /codec2_ofdm.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: codec2_ofdm.h 4 | AUTHORS.....: David Rowe & Steve Sampson 5 | DATE CREATED: June 2017 6 | 7 | External user references to the modem library. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2017 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef CODEC2_OFDM_H 29 | #define CODEC2_OFDM_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* Includes */ 36 | 37 | #include 38 | #include 39 | 40 | #include "comp.h" 41 | #include "modem_stats.h" 42 | 43 | /* Defines */ 44 | 45 | #define OFDM_AMP_SCALE (2E5*1.1491/1.06) /* use to scale to 16 bit short */ 46 | #define OFDM_CLIP (32767*0.35) /* experimentally derived constant to reduce PAPR to about 8dB */ 47 | #define OFDM_SYNC_UNSYNC 0 /* force sync state machine to lose sync, and search for new sync */ 48 | #define OFDM_SYNC_AUTO 1 /* falls out of sync automatically */ 49 | #define OFDM_SYNC_MANUAL 2 /* fall out of sync only under operator control */ 50 | 51 | struct OFDM; 52 | 53 | /* Default configuration for '700D' mode */ 54 | const struct OFDM_CONFIG * OFDM_CONFIG_700D; 55 | 56 | /* create and destroy modem states */ 57 | 58 | struct OFDM *ofdm_create(const struct OFDM_CONFIG * config); 59 | void ofdm_destroy(struct OFDM *); 60 | 61 | /* signal processing */ 62 | 63 | void ofdm_mod(struct OFDM *, COMP *, const int *); 64 | void ofdm_demod(struct OFDM *, int *, COMP *); 65 | int ofdm_sync_search(struct OFDM *ofdm, COMP *rxbuf_in); 66 | void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw); 67 | 68 | /* getters */ 69 | 70 | int ofdm_get_nin(struct OFDM *); 71 | int ofdm_get_samples_per_frame(void); 72 | int ofdm_get_max_samples_per_frame(void); 73 | int ofdm_get_bits_per_frame(struct OFDM *); 74 | void ofdm_get_demod_stats(struct OFDM *ofdm, struct MODEM_STATS *stats); 75 | 76 | /* option setters */ 77 | 78 | void ofdm_set_verbose(struct OFDM *, int); 79 | void ofdm_set_timing_enable(struct OFDM *, bool); 80 | void ofdm_set_foff_est_enable(struct OFDM *, bool); 81 | void ofdm_set_phase_est_enable(struct OFDM *, bool); 82 | void ofdm_set_off_est_hz(struct OFDM *, float); 83 | void ofdm_set_sync(struct OFDM *ofdm, int sync_cmd); 84 | void ofdm_set_tx_bpf(struct OFDM *ofdm, bool); 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | #endif 91 | 92 | -------------------------------------------------------------------------------- /comp.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: comp.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 24/08/09 6 | 7 | Complex number definition. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef __COMP__ 29 | #define __COMP__ 30 | 31 | /* Complex number */ 32 | 33 | typedef struct { 34 | float real; 35 | float imag; 36 | } COMP; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /comp_prim.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: comp_prim.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: Marh 2015 6 | 7 | Complex number maths primitives. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2015 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef __COMP_PRIM__ 29 | #define __COMP_PRIM__ 30 | 31 | /*---------------------------------------------------------------------------*\ 32 | 33 | FUNCTIONS 34 | 35 | \*---------------------------------------------------------------------------*/ 36 | 37 | inline static COMP cneg(COMP a) 38 | { 39 | COMP res; 40 | 41 | res.real = -a.real; 42 | res.imag = -a.imag; 43 | 44 | return res; 45 | } 46 | 47 | inline static COMP cconj(COMP a) 48 | { 49 | COMP res; 50 | 51 | res.real = a.real; 52 | res.imag = -a.imag; 53 | 54 | return res; 55 | } 56 | 57 | inline static COMP cmult(COMP a, COMP b) 58 | { 59 | COMP res; 60 | 61 | res.real = a.real*b.real - a.imag*b.imag; 62 | res.imag = a.real*b.imag + a.imag*b.real; 63 | 64 | return res; 65 | } 66 | 67 | inline static COMP fcmult(float a, COMP b) 68 | { 69 | COMP res; 70 | 71 | res.real = a*b.real; 72 | res.imag = a*b.imag; 73 | 74 | return res; 75 | } 76 | 77 | inline static COMP cadd(COMP a, COMP b) 78 | { 79 | COMP res; 80 | 81 | res.real = a.real + b.real; 82 | res.imag = a.imag + b.imag; 83 | 84 | return res; 85 | } 86 | 87 | inline static float cabsolute(COMP a) 88 | { 89 | return sqrtf(powf(a.real, 2.0) + powf(a.imag, 2.0)); 90 | } 91 | 92 | /* 93 | * Euler's formula in a new convenient function 94 | */ 95 | inline static COMP comp_exp_j(float phi){ 96 | COMP res; 97 | res.real = cosf(phi); 98 | res.imag = sinf(phi); 99 | return res; 100 | } 101 | 102 | /* 103 | * Quick and easy complex 0 104 | */ 105 | inline static COMP comp0(){ 106 | COMP res; 107 | res.real = 0; 108 | res.imag = 0; 109 | return res; 110 | } 111 | 112 | /* 113 | * Quick and easy complex subtract 114 | */ 115 | inline static COMP csub(COMP a, COMP b){ 116 | COMP res; 117 | res.real = a.real-b.real; 118 | res.imag = a.imag-b.imag; 119 | return res; 120 | } 121 | 122 | /* 123 | * Compare the magnitude of a and b. if |a|>|b|, return true, otw false. 124 | * This needs no square roots 125 | */ 126 | inline static int comp_mag_gt(COMP a,COMP b){ 127 | return ((a.real*a.real)+(a.imag*a.imag)) > ((b.real*b.real)+(b.imag*b.imag)); 128 | } 129 | 130 | /* 131 | * Normalize a complex number's magnitude to 1 132 | */ 133 | inline static COMP comp_normalize(COMP a){ 134 | COMP b; 135 | float av = cabsolute(a); 136 | b.real = a.real/av; 137 | b.imag = a.imag/av; 138 | return b; 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /defines.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: defines.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 23/4/93 6 | 7 | Defines and structures used throughout the codec. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef __DEFINES__ 29 | #define __DEFINES__ 30 | 31 | /*---------------------------------------------------------------------------*\ 32 | 33 | DEFINES 34 | 35 | \*---------------------------------------------------------------------------*/ 36 | 37 | /* General defines */ 38 | 39 | #define N_S 0.010 /* buffer size in s */ 40 | #define TW_S 0.005 /* trapezoidal synth window overlap */ 41 | #define MAX_AMP 160 /* maximum number of harmonics */ 42 | #ifndef PI 43 | #define PI 3.141592654 /* mathematical constant */ 44 | #endif 45 | #define TWO_PI 6.283185307 /* mathematical constant */ 46 | #define MAX_STR 2048 /* maximum string size */ 47 | 48 | #define FFT_ENC 512 /* size of FFT used for encoder */ 49 | #define FFT_DEC 512 /* size of FFT used in decoder */ 50 | #define V_THRESH 6.0 /* voicing threshold in dB */ 51 | #define LPC_ORD 10 /* LPC order */ 52 | #define LPC_ORD_LOW 6 /* LPC order for lower rates */ 53 | 54 | /* Pitch estimation defines */ 55 | 56 | #define M_PITCH_S 0.0400 /* pitch analysis window in s */ 57 | #define P_MIN_S 0.0025 /* minimum pitch period in s */ 58 | #define P_MAX_S 0.0200 /* maximum pitch period in s */ 59 | 60 | /*---------------------------------------------------------------------------*\ 61 | 62 | TYPEDEFS 63 | 64 | \*---------------------------------------------------------------------------*/ 65 | 66 | /* Structure to hold constants calculated at run time based on sample rate */ 67 | 68 | typedef struct { 69 | int Fs; /* sample rate of this instance */ 70 | int n_samp; /* number of samples per 10ms frame at Fs */ 71 | int max_amp; /* maximum number of harmonics */ 72 | int m_pitch; /* pitch estimation window size in samples */ 73 | int p_min; /* minimum pitch period in samples */ 74 | int p_max; /* maximum pitch period in samples */ 75 | float Wo_min; 76 | float Wo_max; 77 | int nw; /* analysis window size in samples */ 78 | int tw; /* trapezoidal synthesis window overlap */ 79 | } C2CONST; 80 | 81 | /* Structure to hold model parameters for one frame */ 82 | 83 | typedef struct { 84 | float Wo; /* fundamental frequency estimate in radians */ 85 | int L; /* number of harmonics */ 86 | float A[MAX_AMP+1]; /* amplitiude of each harmonic */ 87 | float phi[MAX_AMP+1]; /* phase of each harmonic */ 88 | int voiced; /* non-zero if this frame is voiced */ 89 | } MODEL; 90 | 91 | /* describes each codebook */ 92 | 93 | struct lsp_codebook { 94 | int k; /* dimension of vector */ 95 | int log2m; /* number of bits in m */ 96 | int m; /* elements in codebook */ 97 | const float * cb; /* The elements */ 98 | }; 99 | 100 | extern const struct lsp_codebook lsp_cb[]; 101 | extern const struct lsp_codebook lsp_cbd[]; 102 | extern const struct lsp_codebook lsp_cbvq[]; 103 | extern const struct lsp_codebook lsp_cbjnd[]; 104 | extern const struct lsp_codebook lsp_cbdt[]; 105 | extern const struct lsp_codebook lsp_cbjvm[]; 106 | extern const struct lsp_codebook lsp_cbvqanssi[]; 107 | extern const struct lsp_codebook mel_cb[]; 108 | extern const struct lsp_codebook ge_cb[]; 109 | extern const struct lsp_codebook lspmelvq_cb[]; 110 | extern const struct lsp_codebook newamp1vq_cb[]; 111 | extern const struct lsp_codebook newamp1_energy_cb[]; 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /dump.c: -------------------------------------------------------------------------------- 1 | //as usual... 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //internet 9 | #include 10 | #include 11 | 12 | //colors 13 | #define ANSI_COLOR_RED "\x1b[31m" 14 | #define ANSI_COLOR_GREEN "\x1b[32m" 15 | #define ANSI_COLOR_YELLOW "\x1b[33m" 16 | #define ANSI_COLOR_BLUE "\x1b[34m" 17 | #define ANSI_COLOR_MAGENTA "\x1b[35m" 18 | #define ANSI_COLOR_CYAN "\x1b[36m" 19 | #define ANSI_COLOR_RESET "\x1b[0m" 20 | 21 | //port 22 | uint16_t port_num=17000; //default port 23 | 24 | //UDP packet 25 | uint8_t bits[54]; 26 | 27 | //internet 28 | struct sockaddr_in si_me, si_other; 29 | int s, i, slen = sizeof(si_other) , rcv_len; 30 | 31 | //CRC 32 | uint16_t CRC_LUT[256]; 33 | uint16_t poly=0x5935; 34 | 35 | //test 36 | //FILE *fp; 37 | 38 | //stream info 39 | struct moip_packet 40 | { 41 | uint16_t sid; 42 | uint8_t src[10]; 43 | uint8_t dst[10]; 44 | uint16_t type; 45 | uint8_t nonce[14]; 46 | uint16_t fn; 47 | uint8_t payload[16]; 48 | uint16_t crc_udp; 49 | } packet; 50 | 51 | void CRC_Init(uint16_t *crc_table, uint16_t poly) 52 | { 53 | uint16_t remainder; 54 | 55 | for(uint16_t dividend=0; dividend<256; dividend++) 56 | { 57 | remainder=dividend<<8; 58 | 59 | for(uint8_t bit=8; bit>0; bit--) 60 | { 61 | if(remainder&(1<<15)) 62 | remainder=(remainder<<1)^poly; 63 | else 64 | remainder=(remainder<<1); 65 | } 66 | 67 | crc_table[dividend]=remainder; 68 | } 69 | } 70 | 71 | uint16_t CRC_M17(uint16_t* crc_table, const uint8_t* message, uint16_t nBytes) 72 | { 73 | uint8_t data; 74 | uint16_t remainder=0xFFFF; 75 | 76 | for(uint16_t byte=0; byte>8); 79 | remainder=crc_table[data]^(remainder<<8); 80 | } 81 | 82 | return(remainder); 83 | } 84 | 85 | uint8_t* decode_callsign_base40(uint64_t encoded, uint8_t *callsign) 86 | { 87 | if(encoded >= 262144000000000) 88 | { 89 | *callsign=0; 90 | return callsign; 91 | } 92 | 93 | uint8_t *p = callsign; 94 | 95 | for (; encoded>0; p++) 96 | { 97 | *p = "xABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded % 40]; 98 | encoded/=40; 99 | } 100 | 101 | *p = 0; 102 | 103 | return callsign; 104 | } 105 | 106 | // ./this.out port 107 | int main(int argc, char *argv[]) 108 | { 109 | if(argc==2) 110 | { 111 | port_num=atoi(argv[1]); 112 | } 113 | else 114 | { 115 | fprintf(stderr, ANSI_COLOR_RED "Not enough args" ANSI_COLOR_RESET "\n"); 116 | return 1; 117 | } 118 | 119 | //init 120 | memset(bits, 0, 54); 121 | CRC_Init(CRC_LUT, poly); 122 | 123 | s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 124 | 125 | if(s==-1) 126 | { 127 | fprintf(stderr, ANSI_COLOR_RED "Socket error" ANSI_COLOR_RESET "\n"); 128 | return 1; 129 | } 130 | 131 | //zero out the structure 132 | memset((char*)&si_me, 0, sizeof(si_me)); 133 | 134 | si_me.sin_family = AF_INET; 135 | si_me.sin_port = htons(port_num); 136 | si_me.sin_addr.s_addr = htonl(INADDR_ANY); 137 | 138 | if(bind(s, (struct sockaddr*)&si_me, sizeof(si_me))==-1) 139 | { 140 | fprintf(stderr, ANSI_COLOR_RED "Can't bind to port %d" ANSI_COLOR_RESET "\n", port_num); 141 | return 1; 142 | } 143 | 144 | printf("Listening for M17 frames on port %d:\n", port_num); 145 | printf(" FN\t Src\t\t Dst\t\tType\tSID\trCRC\tcCRC\tPld\n"); 146 | 147 | while(1) 148 | { 149 | //receive packet via UDP 150 | if((rcv_len=recvfrom(s, bits, 54, 0, (struct sockaddr*)&si_other, &slen))==-1) 151 | { 152 | fprintf(stderr, "What the hell?\n"); 153 | return 1; 154 | } 155 | 156 | if(rcv_len==54) 157 | { 158 | packet.sid=((uint16_t)bits[4]<<8)|bits[5]; 159 | uint64_t tmp; 160 | tmp=((uint64_t)bits[6]<<(5*8))|((uint64_t)bits[7]<<(4*8))|((uint64_t)bits[8]<<(3*8))|((uint64_t)bits[9]<<(2*8))|((uint64_t)bits[10]<<(1*8))|(uint64_t)bits[11]; 161 | decode_callsign_base40(tmp, packet.dst); 162 | tmp=((uint64_t)bits[12]<<(5*8))|((uint64_t)bits[13]<<(4*8))|((uint64_t)bits[14]<<(3*8))|((uint64_t)bits[15]<<(2*8))|((uint64_t)bits[16]<<(1*8))|(uint64_t)bits[17]; 163 | decode_callsign_base40(tmp, packet.src); 164 | packet.type=((uint16_t)bits[18]<<8)|bits[19]; 165 | 166 | memcpy(packet.nonce, &bits[20], 14); 167 | packet.fn=((uint16_t)bits[34]<<8)|(uint16_t)bits[35]; 168 | memcpy(packet.payload, &bits[36], 16); 169 | packet.crc_udp=((uint16_t)bits[52]<<8)|(uint16_t)bits[53]; 170 | uint16_t local_crc=CRC_M17(CRC_LUT, bits, 52); 171 | 172 | //info 173 | if(packet.crc_udp!=local_crc) 174 | printf(ANSI_COLOR_YELLOW); 175 | 176 | printf("%6d\t%10s\t%10s\t%4X\t%04X\t%04X\t%04X\t", packet.fn, packet.src, packet.dst, packet.type, packet.sid, packet.crc_udp, local_crc); 177 | for(uint8_t i=0; i<128/8; i++) 178 | printf("%02X", packet.payload[i]); 179 | 180 | if(packet.crc_udp!=local_crc) 181 | printf(ANSI_COLOR_RESET); 182 | printf("\n"); 183 | 184 | /*fp=fopen("out.raw", "a"); 185 | fwrite(speech_buff, 2, 160, fp); 186 | fclose(fp);*/ 187 | } 188 | } 189 | 190 | return 0; 191 | } 192 | -------------------------------------------------------------------------------- /dump.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: dump.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 25/8/09 6 | 7 | Routines to dump data to text files for Octave analysis. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | All rights reserved. 13 | 14 | This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU Lesser General Public License version 2.1, as 16 | published by the Free Software Foundation. This program is 17 | distributed in the hope that it will be useful, but WITHOUT ANY 18 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 20 | License for more details. 21 | 22 | You should have received a copy of the GNU Lesser General Public License 23 | along with this program; if not, see . 24 | */ 25 | 26 | #ifndef __DUMP__ 27 | #define __DUMP__ 28 | 29 | #include "defines.h" 30 | #include "comp.h" 31 | #include "codec2_fft.h" 32 | #include "codec2_internal.h" 33 | 34 | void dump_on(char filename_prefix[]); 35 | void dump_off(); 36 | 37 | void dump_Sn(int m_pitch, float Sn[]); 38 | void dump_Sw(COMP Sw[]); 39 | void dump_Sw_(COMP Sw_[]); 40 | void dump_Ew(COMP Ew[]); 41 | void dump_softdec(float *softdec, int n); 42 | 43 | /* amplitude modelling */ 44 | 45 | void dump_model(MODEL *m); 46 | void dump_quantised_model(MODEL *m); 47 | void dump_Pwn(COMP Pw[]); 48 | void dump_Pw(float Pw[]); 49 | void dump_Rw(float Rw[]); 50 | void dump_lsp(float lsp[]); 51 | void dump_weights(float w[], int ndim); 52 | void dump_lsp_(float lsp_[]); 53 | void dump_mel(float mel[], int order); 54 | void dump_mel_indexes(int mel_indexes[], int order); 55 | void dump_ak(float ak[], int order); 56 | void dump_ak_(float ak[], int order); 57 | void dump_E(float E); 58 | void dump_lpc_snr(float snr); 59 | 60 | /* phase modelling */ 61 | 62 | void dump_snr(float snr); 63 | void dump_phase(float phase[], int L); 64 | void dump_phase_(float phase[], int L); 65 | void dump_hephase(int ind[], int dim); 66 | 67 | /* NLP states */ 68 | 69 | void dump_sq(int m_pitch, float sq[]); 70 | void dump_dec(COMP Fw[]); 71 | void dump_Fw(COMP Fw[]); 72 | void dump_e(float e_hz[]); 73 | #if 0 74 | void dump_Rk(float Rk[]); 75 | #endif 76 | 77 | /* post filter */ 78 | 79 | void dump_bg(float e, float bg_est, float percent_uv); 80 | void dump_Pwb(float Pwb[]); 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /gp_interleaver.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: gp_interleaver.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: April 2018 6 | 7 | Golden Prime Interleaver. My interpretation of "On the Analysis and 8 | Design of Good Algebraic Interleavers", Xie et al,eq (5). 9 | 10 | See also octvae/gp_interleaver.m 11 | 12 | \*---------------------------------------------------------------------------*/ 13 | 14 | /* 15 | Copyright (C) 2018 David Rowe 16 | 17 | All rights reserved. 18 | 19 | This program is free software; you can redistribute it and/or modify 20 | it under the terms of the GNU Lesser General Public License version 2.1, as 21 | published by the Free Software Foundation. This program is 22 | distributed in the hope that it will be useful, but WITHOUT ANY 23 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 25 | License for more details. 26 | 27 | You should have received a copy of the GNU Lesser General Public License 28 | along with this program; if not, see . 29 | */ 30 | 31 | #include 32 | #include 33 | #include "gp_interleaver.h" 34 | 35 | /* 36 | Choose b for Golden Prime Interleaver. b is chosen to be the 37 | closest integer, which is relatively prime to N, to the Golden 38 | section of N. 39 | 40 | Implemented with a LUT in C for convenience, Octave version 41 | has a more complete implementation. 42 | */ 43 | 44 | int b_table[] = { 45 | 112,71, 46 | 224,139, 47 | 448,277, 48 | 672,419, 49 | 896,557, 50 | 1120,701, 51 | 1344,839, 52 | 1568,971, 53 | 1792,1109, 54 | 2016,1249, 55 | 2240,1399, 56 | 2464,1523, 57 | 2688,1663, 58 | 2912,1801, 59 | 3136,1949, 60 | 3360,2081, 61 | 3584,2213 62 | }; 63 | 64 | int choose_interleaver_b(int Nbits) 65 | { 66 | int i; 67 | 68 | for(i=0; i. 29 | */ 30 | 31 | #ifndef __GP_INTERLEAVER__ 32 | #define __GP_INTERLEAVER__ 33 | 34 | #include "comp.h" 35 | 36 | void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits); 37 | void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits); 38 | void gp_interleave_float(float frame[], float interleaved_frame[], int Nbits); 39 | void gp_deinterleave_float(float interleaved_frame[], float frame[], int Nbits); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /interldpc.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: interldpc.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: April 2018 6 | 7 | Helper functions for interleaved LDPC waveforms. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2018 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | //#include 34 | 35 | #include "interldpc.h" 36 | #include "codec2_ofdm.h" 37 | #include "mpdecode_core.h" 38 | #include "gp_interleaver.h" 39 | #include "HRA_112_112.h" 40 | #include "test_bits_ofdm.h" 41 | 42 | /* CRC type function, used to compare QPSK vectors when debugging */ 43 | 44 | COMP test_acc(COMP v[], int n) { 45 | COMP acc = {0.0,0.0}; 46 | int i; 47 | for(i=0; imax_iter = HRA_112_112_MAX_ITER; 64 | ldpc->dec_type = 0; 65 | ldpc->q_scale_factor = 1; 66 | ldpc->r_scale_factor = 1; 67 | ldpc->CodeLength = HRA_112_112_CODELENGTH; 68 | ldpc->NumberParityBits = HRA_112_112_NUMBERPARITYBITS; 69 | ldpc->NumberRowsHcols = HRA_112_112_NUMBERROWSHCOLS; 70 | ldpc->max_row_weight = HRA_112_112_MAX_ROW_WEIGHT; 71 | ldpc->max_col_weight = HRA_112_112_MAX_COL_WEIGHT; 72 | ldpc->H_rows = HRA_112_112_H_rows; 73 | ldpc->H_cols = HRA_112_112_H_cols; 74 | 75 | /* provided for convenience and to match Octave vaiable names */ 76 | 77 | ldpc->data_bits_per_frame = HRA_112_112_CODELENGTH - HRA_112_112_NUMBERPARITYBITS; 78 | ldpc->coded_bits_per_frame = HRA_112_112_CODELENGTH; 79 | ldpc->coded_syms_per_frame = ldpc->coded_bits_per_frame/OFDM_BPS; 80 | } 81 | 82 | void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]) { 83 | unsigned char pbits[ldpc->NumberParityBits]; 84 | int i,j; 85 | 86 | encode(ldpc, tx_bits_char, pbits); 87 | for(i=0; idata_bits_per_frame; i++) { 88 | codeword[i] = tx_bits_char[i]; 89 | } 90 | for(j=0; icoded_bits_per_frame; i++,j++) { 91 | codeword[i] = pbits[j]; 92 | } 93 | } 94 | 95 | void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n) { 96 | int s,i; 97 | int dibit[2]; 98 | complex float qpsk_symb; 99 | 100 | for(s=0,i=0; icoded_syms_per_frame; 117 | int coded_bits_per_frame = ldpc->coded_bits_per_frame; 118 | int data_bits_per_frame = ldpc->data_bits_per_frame; 119 | double llr[coded_bits_per_frame]; 120 | char out_char[coded_bits_per_frame]; 121 | char next_sync_state_interleaver[OFDM_STATE_STR]; 122 | 123 | strcpy(next_sync_state_interleaver, ofdm->sync_state_interleaver); 124 | if ((strcmp(ofdm->sync_state_interleaver,"search") == 0) && (ofdm->frame_count >= (interleave_frames-1))) { 125 | symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, ofdm->mean_amp, coded_syms_per_frame); 126 | iter[0] = run_ldpc_decoder(ldpc, out_char, llr, parityCheckCount); 127 | Nerrs_coded[0] = data_bits_per_frame - parityCheckCount[0]; 128 | //for(i=0; i<20; i++) 129 | // fprintf(stderr,"%d ", out_char[i]); 130 | //fprintf(stderr,"\n"); 131 | //fprintf(stderr, " iter: %d pcc: %d Nerrs: %d\n", iter[0], parityCheckCount[0], Nerrs_coded[0]); 132 | if ((Nerrs_coded[0] == 0) || (interleave_frames == 1)) { 133 | /* sucessful decode! */ 134 | strcpy(next_sync_state_interleaver, "synced"); 135 | ofdm->frame_count_interleaver = interleave_frames; 136 | } 137 | } 138 | strcpy(ofdm->sync_state_interleaver, next_sync_state_interleaver); 139 | } 140 | 141 | 142 | /* measure uncoded (raw) bit errors over interleaver frame */ 143 | 144 | int count_uncoded_errors(struct LDPC *ldpc, int Nerrs_raw[], int interleave_frames, COMP codeword_symbols_de[]) 145 | { 146 | int i,j,Nerrs,Terrs; 147 | 148 | int coded_syms_per_frame = ldpc->coded_syms_per_frame; 149 | int coded_bits_per_frame = ldpc->coded_bits_per_frame; 150 | int rx_bits_raw[coded_bits_per_frame]; 151 | 152 | assert(sizeof(test_codeword)/sizeof(int) == coded_bits_per_frame); 153 | 154 | Terrs = 0; 155 | for (j=0; jtx_uw[i]; 203 | } 204 | /* clear txt bits for now, they can be added in later */ 205 | for(j=0; jcoded_syms_per_frame; 228 | int coded_bits_per_frame = ldpc->coded_bits_per_frame; 229 | int data_bits_per_frame = ldpc->data_bits_per_frame; 230 | 231 | int codeword[coded_bits_per_frame]; 232 | COMP coded_symbols[interleave_frames*coded_syms_per_frame]; 233 | COMP coded_symbols_inter[interleave_frames*coded_syms_per_frame]; 234 | int Nsamperframe = ofdm_get_samples_per_frame(); 235 | complex float tx_symbols[OFDM_BITSPERFRAME/OFDM_BPS]; 236 | int j; 237 | 238 | for (j=0; j. 26 | */ 27 | 28 | #ifndef __INTERLDPC__ 29 | #define __INTERLDPC__ 30 | 31 | #include 32 | #include "comp.h" 33 | #include "mpdecode_core.h" 34 | #include "ofdm_internal.h" 35 | 36 | /* CRC type function, used to compare QPSK vectors when debugging */ 37 | 38 | COMP test_acc(COMP v[], int n); 39 | void printf_n(COMP v[], int n); 40 | void set_up_hra_112_112(struct LDPC *ldpc); 41 | void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]); 42 | void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n); 43 | void interleaver_sync_state_machine(struct OFDM *ofdm, 44 | struct LDPC *ldpc, 45 | COMP codeword_symbols_de[], 46 | float codeword_amps_de[], 47 | float EsNo, int interleave_frames, 48 | int *inter, int *parityCheckCount, int *Nerrs_coded); 49 | int count_uncoded_errors(struct LDPC *ldpc, int Nerrs_raw[], int interleave_frames, COMP codeword_symbols_de[]); 50 | int count_errors(int tx_bits[], char rx_bits[], int n); 51 | void ofdm_ldpc_interleave_tx(struct OFDM *ofdm, struct LDPC *ldpc, complex float tx_sams[], uint8_t tx_bits[], uint8_t txt_bits[], int interleave_frames); 52 | void build_modulated_uw(struct OFDM *ofdm, complex float tx_symbols[], uint8_t txt_bits[]); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /interp.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: interp.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 9/10/09 6 | 7 | Interpolation of 20ms frames to 10ms frames. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef __INTERP__ 29 | #define __INTERP__ 30 | 31 | #include "kiss_fft.h" 32 | 33 | void interpolate(MODEL *interp, MODEL *prev, MODEL *next); 34 | void interpolate_lsp(kiss_fft_cfg fft_dec_cfg, 35 | MODEL *interp, MODEL *prev, MODEL *next, 36 | float *prev_lsps, float prev_e, 37 | float *next_lsps, float next_e, 38 | float *ak_interp, float *lsps_interp, float Wo_min); 39 | void interp_Wo(MODEL *interp, MODEL *prev, MODEL *next, float Wo_min); 40 | void interp_Wo2(MODEL *interp, MODEL *prev, MODEL *next, float weight, float Wo_min); 41 | float interp_energy(float prev, float next); 42 | float interp_energy2(float prev, float next, float weight); 43 | void interpolate_lsp_ver2(float interp[], float prev[], float next[], float weight, int order); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /kiss_fft.h: -------------------------------------------------------------------------------- 1 | #ifndef KISS_FFT_H 2 | #define KISS_FFT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /* 14 | ATTENTION! 15 | If you would like a : 16 | -- a utility that will handle the caching of fft objects 17 | -- real-only (no imaginary time component ) FFT 18 | -- a multi-dimensional FFT 19 | -- a command-line utility to perform ffts 20 | -- a command-line utility to perform fast-convolution filtering 21 | 22 | Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c 23 | in the tools/ directory. 24 | */ 25 | 26 | #ifdef USE_SIMD 27 | # include 28 | # define kiss_fft_scalar __m128 29 | #define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) 30 | #define KISS_FFT_FREE _mm_free 31 | #else 32 | #define KISS_FFT_MALLOC malloc 33 | #define KISS_FFT_FREE free 34 | #endif 35 | 36 | 37 | #ifdef FIXED_POINT 38 | #include 39 | # if (FIXED_POINT == 32) 40 | # define kiss_fft_scalar int32_t 41 | # else 42 | # define kiss_fft_scalar int16_t 43 | # endif 44 | #else 45 | # ifndef kiss_fft_scalar 46 | /* default is float */ 47 | # define kiss_fft_scalar float 48 | # endif 49 | #endif 50 | 51 | typedef struct { 52 | kiss_fft_scalar r; 53 | kiss_fft_scalar i; 54 | }kiss_fft_cpx; 55 | 56 | typedef struct kiss_fft_state* kiss_fft_cfg; 57 | 58 | /* 59 | * kiss_fft_alloc 60 | * 61 | * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. 62 | * 63 | * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); 64 | * 65 | * The return value from fft_alloc is a cfg buffer used internally 66 | * by the fft routine or NULL. 67 | * 68 | * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. 69 | * The returned value should be free()d when done to avoid memory leaks. 70 | * 71 | * The state can be placed in a user supplied buffer 'mem': 72 | * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, 73 | * then the function places the cfg in mem and the size used in *lenmem 74 | * and returns mem. 75 | * 76 | * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), 77 | * then the function returns NULL and places the minimum cfg 78 | * buffer size in *lenmem. 79 | * */ 80 | 81 | kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); 82 | 83 | /* 84 | * kiss_fft(cfg,in_out_buf) 85 | * 86 | * Perform an FFT on a complex input buffer. 87 | * for a forward FFT, 88 | * fin should be f[0] , f[1] , ... ,f[nfft-1] 89 | * fout will be F[0] , F[1] , ... ,F[nfft-1] 90 | * Note that each element is complex and can be accessed like 91 | f[k].r and f[k].i 92 | * */ 93 | void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); 94 | 95 | /* 96 | A more generic version of the above function. It reads its input from every Nth sample. 97 | * */ 98 | void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); 99 | 100 | /* If kiss_fft_alloc allocated a buffer, it is one contiguous 101 | buffer and can be simply free()d when no longer needed*/ 102 | #define kiss_fft_free free 103 | 104 | /* 105 | Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up 106 | your compiler output to call this before you exit. 107 | */ 108 | void kiss_fft_cleanup(void); 109 | 110 | 111 | /* 112 | * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) 113 | */ 114 | int kiss_fft_next_fast_size(int n); 115 | 116 | /* for real ffts, we need an even size */ 117 | #define kiss_fftr_next_fast_size_real(n) \ 118 | (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) 119 | 120 | #ifdef __cplusplus 121 | } 122 | #endif 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /kiss_fftr.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2004, Mark Borgerding 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | * 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. 10 | * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | 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 COPYRIGHT OWNER 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. 13 | */ 14 | 15 | #include "kiss_fftr.h" 16 | #include "_kiss_fft_guts.h" 17 | #include "assert.h" 18 | 19 | struct kiss_fftr_state{ 20 | kiss_fft_cfg substate; 21 | kiss_fft_cpx * tmpbuf; 22 | kiss_fft_cpx * super_twiddles; 23 | #ifdef USE_SIMD 24 | void * pad; 25 | #endif 26 | }; 27 | 28 | kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) 29 | { 30 | int i; 31 | kiss_fftr_cfg st = NULL; 32 | size_t subsize, memneeded; 33 | 34 | if (nfft & 1) { 35 | fprintf(stderr,"Real FFT optimization must be even.\n"); 36 | return NULL; 37 | } 38 | nfft >>= 1; 39 | 40 | kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); 41 | memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2); 42 | 43 | if (lenmem == NULL) { 44 | st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); 45 | } else { 46 | if (*lenmem >= memneeded) 47 | st = (kiss_fftr_cfg) mem; 48 | *lenmem = memneeded; 49 | } 50 | if (!st) 51 | return NULL; 52 | 53 | st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ 54 | st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); 55 | st->super_twiddles = st->tmpbuf + nfft; 56 | kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); 57 | 58 | for (i = 0; i < nfft/2; ++i) { 59 | float phase = 60 | -3.14159265358979323846264338327 * ((float) (i+1) / nfft + .5); 61 | if (inverse_fft) 62 | phase *= -1; 63 | kf_cexp (st->super_twiddles+i,phase); 64 | } 65 | return st; 66 | } 67 | 68 | void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) 69 | { 70 | /* input buffer timedata is stored row-wise */ 71 | int k,ncfft; 72 | kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; 73 | 74 | assert(st->substate->inverse==0); 75 | 76 | ncfft = st->substate->nfft; 77 | 78 | /*perform the parallel fft of two real signals packed in real,imag*/ 79 | kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); 80 | /* The real part of the DC element of the frequency spectrum in st->tmpbuf 81 | * contains the sum of the even-numbered elements of the input time sequence 82 | * The imag part is the sum of the odd-numbered elements 83 | * 84 | * The sum of tdc.r and tdc.i is the sum of the input time sequence. 85 | * yielding DC of input time sequence 86 | * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... 87 | * yielding Nyquist bin of input time sequence 88 | */ 89 | 90 | tdc.r = st->tmpbuf[0].r; 91 | tdc.i = st->tmpbuf[0].i; 92 | C_FIXDIV(tdc,2); 93 | CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); 94 | CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); 95 | freqdata[0].r = tdc.r + tdc.i; 96 | freqdata[ncfft].r = tdc.r - tdc.i; 97 | #ifdef USE_SIMD 98 | freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); 99 | #else 100 | freqdata[ncfft].i = freqdata[0].i = 0; 101 | #endif 102 | 103 | for ( k=1;k <= ncfft/2 ; ++k ) { 104 | fpk = st->tmpbuf[k]; 105 | fpnk.r = st->tmpbuf[ncfft-k].r; 106 | fpnk.i = - st->tmpbuf[ncfft-k].i; 107 | C_FIXDIV(fpk,2); 108 | C_FIXDIV(fpnk,2); 109 | 110 | C_ADD( f1k, fpk , fpnk ); 111 | C_SUB( f2k, fpk , fpnk ); 112 | C_MUL( tw , f2k , st->super_twiddles[k-1]); 113 | 114 | freqdata[k].r = HALF_OF(f1k.r + tw.r); 115 | freqdata[k].i = HALF_OF(f1k.i + tw.i); 116 | freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); 117 | freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); 118 | } 119 | } 120 | 121 | void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) 122 | { 123 | /* input buffer timedata is stored row-wise */ 124 | int k, ncfft; 125 | 126 | assert(st->substate->inverse == 1); 127 | 128 | ncfft = st->substate->nfft; 129 | 130 | st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; 131 | st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; 132 | C_FIXDIV(st->tmpbuf[0],2); 133 | 134 | for (k = 1; k <= ncfft / 2; ++k) { 135 | kiss_fft_cpx fk, fnkc, fek, fok, tmp; 136 | fk = freqdata[k]; 137 | fnkc.r = freqdata[ncfft - k].r; 138 | fnkc.i = -freqdata[ncfft - k].i; 139 | C_FIXDIV( fk , 2 ); 140 | C_FIXDIV( fnkc , 2 ); 141 | 142 | C_ADD (fek, fk, fnkc); 143 | C_SUB (tmp, fk, fnkc); 144 | C_MUL (fok, tmp, st->super_twiddles[k-1]); 145 | C_ADD (st->tmpbuf[k], fek, fok); 146 | C_SUB (st->tmpbuf[ncfft - k], fek, fok); 147 | #ifdef USE_SIMD 148 | st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); 149 | #else 150 | st->tmpbuf[ncfft - k].i *= -1; 151 | #endif 152 | } 153 | kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); 154 | } 155 | -------------------------------------------------------------------------------- /kiss_fftr.h: -------------------------------------------------------------------------------- 1 | #ifndef KISS_FTR_H 2 | #define KISS_FTR_H 3 | 4 | #include "kiss_fft.h" 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | 10 | /* 11 | 12 | Real optimized version can save about 45% cpu time vs. complex fft of a real seq. 13 | 14 | 15 | 16 | */ 17 | 18 | typedef struct kiss_fftr_state *kiss_fftr_cfg; 19 | 20 | 21 | kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); 22 | /* 23 | nfft must be even 24 | 25 | If you don't care to allocate space, use mem = lenmem = NULL 26 | */ 27 | 28 | 29 | void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); 30 | /* 31 | input timedata has nfft scalar points 32 | output freqdata has nfft/2+1 complex points 33 | */ 34 | 35 | void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); 36 | /* 37 | input freqdata has nfft/2+1 complex points 38 | output timedata has nfft scalar points 39 | */ 40 | 41 | #define kiss_fftr_free free 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | #endif 47 | -------------------------------------------------------------------------------- /lpc.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: lpc.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 30 Sep 1990 (!) 6 | 7 | Linear Prediction functions written in C. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009-2012 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #define LPC_MAX_N 512 /* maximum no. of samples in frame */ 29 | #define PI 3.141592654 /* mathematical constant */ 30 | 31 | #define ALPHA 1.0 32 | #define BETA 0.94 33 | 34 | #include 35 | #include 36 | #include "defines.h" 37 | #include "lpc.h" 38 | 39 | /*---------------------------------------------------------------------------*\ 40 | 41 | pre_emp() 42 | 43 | Pre-emphasise (high pass filter with zero close to 0 Hz) a frame of 44 | speech samples. Helps reduce dynamic range of LPC spectrum, giving 45 | greater weight and hense a better match to low energy formants. 46 | 47 | Should be balanced by de-emphasis of the output speech. 48 | 49 | \*---------------------------------------------------------------------------*/ 50 | 51 | void pre_emp( 52 | float Sn_pre[], /* output frame of speech samples */ 53 | float Sn[], /* input frame of speech samples */ 54 | float *mem, /* Sn[-1]single sample memory */ 55 | int Nsam /* number of speech samples to use */ 56 | ) 57 | { 58 | int i; 59 | 60 | for(i=0; i 1.0) 171 | k = 0.0; 172 | 173 | a[i][i] = k; 174 | 175 | for(j=1; j<=i-1; j++) 176 | a[i][j] = a[i-1][j] + k*a[i-1][i-j]; /* Equation 38c, Makhoul */ 177 | 178 | e *= (1-k*k); /* Equation 38d, Makhoul */ 179 | } 180 | 181 | for(i=1; i<=order; i++) 182 | lpcs[i] = a[order][i]; 183 | lpcs[0] = 1.0; 184 | } 185 | 186 | /*---------------------------------------------------------------------------*\ 187 | 188 | inverse_filter() 189 | 190 | Inverse Filter, A(z). Produces an array of residual samples from an array 191 | of input samples and linear prediction coefficients. 192 | 193 | The filter memory is stored in the first order samples of the input array. 194 | 195 | \*---------------------------------------------------------------------------*/ 196 | 197 | void inverse_filter( 198 | float Sn[], /* Nsam input samples */ 199 | float a[], /* LPCs for this frame of samples */ 200 | int Nsam, /* number of samples */ 201 | float res[], /* Nsam residual samples */ 202 | int order /* order of LPC */ 203 | ) 204 | { 205 | int i,j; /* loop variables */ 206 | 207 | for(i=0; i. 26 | */ 27 | 28 | #ifndef __LPC__ 29 | #define __LPC__ 30 | 31 | #define LPC_MAX_ORDER 20 32 | 33 | void pre_emp(float Sn_pre[], float Sn[], float *mem, int Nsam); 34 | void de_emp(float Sn_se[], float Sn[], float *mem, int Nsam); 35 | void hanning_window(float Sn[], float Wn[], int Nsam); 36 | void autocorrelate(float Sn[], float Rn[], int Nsam, int order); 37 | void levinson_durbin(float R[], float lpcs[], int order); 38 | void inverse_filter(float Sn[], float a[], int Nsam, float res[], int order); 39 | void synthesis_filter(float res[], float a[], int Nsam, int order, float Sn_[]); 40 | void find_aks(float Sn[], float a[], int Nsam, int order, float *E); 41 | void weight(float ak[], float gamma, int order, float akw[]); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /lsp.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: lsp.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 24/2/93 6 | 7 | 8 | This file contains functions for LPC to LSP conversion and LSP to 9 | LPC conversion. Note that the LSP coefficients are not in radians 10 | format but in the x domain of the unit circle. 11 | 12 | \*---------------------------------------------------------------------------*/ 13 | 14 | /* 15 | Copyright (C) 2009 David Rowe 16 | 17 | All rights reserved. 18 | 19 | This program is free software; you can redistribute it and/or modify 20 | it under the terms of the GNU Lesser General Public License version 2.1, as 21 | published by the Free Software Foundation. This program is 22 | distributed in the hope that it will be useful, but WITHOUT ANY 23 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 25 | License for more details. 26 | 27 | You should have received a copy of the GNU Lesser General Public License 28 | along with this program; if not, see . 29 | */ 30 | 31 | #include "defines.h" 32 | #include "lsp.h" 33 | #include 34 | #include 35 | #include 36 | 37 | /*---------------------------------------------------------------------------*\ 38 | 39 | Introduction to Line Spectrum Pairs (LSPs) 40 | ------------------------------------------ 41 | 42 | LSPs are used to encode the LPC filter coefficients {ak} for 43 | transmission over the channel. LSPs have several properties (like 44 | less sensitivity to quantisation noise) that make them superior to 45 | direct quantisation of {ak}. 46 | 47 | A(z) is a polynomial of order lpcrdr with {ak} as the coefficients. 48 | 49 | A(z) is transformed to P(z) and Q(z) (using a substitution and some 50 | algebra), to obtain something like: 51 | 52 | A(z) = 0.5[P(z)(z+z^-1) + Q(z)(z-z^-1)] (1) 53 | 54 | As you can imagine A(z) has complex zeros all over the z-plane. P(z) 55 | and Q(z) have the very neat property of only having zeros _on_ the 56 | unit circle. So to find them we take a test point z=exp(jw) and 57 | evaluate P (exp(jw)) and Q(exp(jw)) using a grid of points between 0 58 | and pi. 59 | 60 | The zeros (roots) of P(z) also happen to alternate, which is why we 61 | swap coefficients as we find roots. So the process of finding the 62 | LSP frequencies is basically finding the roots of 5th order 63 | polynomials. 64 | 65 | The root so P(z) and Q(z) occur in symmetrical pairs at +/-w, hence 66 | the name Line Spectrum Pairs (LSPs). 67 | 68 | To convert back to ak we just evaluate (1), "clocking" an impulse 69 | thru it lpcrdr times gives us the impulse response of A(z) which is 70 | {ak}. 71 | 72 | \*---------------------------------------------------------------------------*/ 73 | 74 | /*---------------------------------------------------------------------------*\ 75 | 76 | FUNCTION....: cheb_poly_eva() 77 | AUTHOR......: David Rowe 78 | DATE CREATED: 24/2/93 79 | 80 | This function evalutes a series of chebyshev polynomials 81 | 82 | FIXME: performing memory allocation at run time is very inefficient, 83 | replace with stack variables of MAX_P size. 84 | 85 | \*---------------------------------------------------------------------------*/ 86 | 87 | 88 | static float 89 | cheb_poly_eva(float *coef,float x,int order) 90 | /* float coef[] coefficients of the polynomial to be evaluated */ 91 | /* float x the point where polynomial is to be evaluated */ 92 | /* int order order of the polynomial */ 93 | { 94 | int i; 95 | float *t,*u,*v,sum; 96 | float T[(order / 2) + 1]; 97 | 98 | /* Initialise pointers */ 99 | 100 | t = T; /* T[i-2] */ 101 | *t++ = 1.0; 102 | u = t--; /* T[i-1] */ 103 | *u++ = x; 104 | v = u--; /* T[i] */ 105 | 106 | /* Evaluate chebyshev series formulation using iterative approach */ 107 | 108 | for(i=2;i<=order/2;i++) 109 | *v++ = (2*x)*(*u++) - *t++; /* T[i] = 2*x*T[i-1] - T[i-2] */ 110 | 111 | sum=0.0; /* initialise sum to zero */ 112 | t = T; /* reset pointer */ 113 | 114 | /* Evaluate polynomial and return value also free memory space */ 115 | 116 | for(i=0;i<=order/2;i++) 117 | sum+=coef[(order/2)-i]**t++; 118 | 119 | return sum; 120 | } 121 | 122 | 123 | /*---------------------------------------------------------------------------*\ 124 | 125 | FUNCTION....: lpc_to_lsp() 126 | AUTHOR......: David Rowe 127 | DATE CREATED: 24/2/93 128 | 129 | This function converts LPC coefficients to LSP coefficients. 130 | 131 | \*---------------------------------------------------------------------------*/ 132 | 133 | int lpc_to_lsp (float *a, int order, float *freq, int nb, float delta) 134 | /* float *a lpc coefficients */ 135 | /* int order order of LPC coefficients (10) */ 136 | /* float *freq LSP frequencies in radians */ 137 | /* int nb number of sub-intervals (4) */ 138 | /* float delta grid spacing interval (0.02) */ 139 | { 140 | float psuml,psumr,psumm,temp_xr,xl,xr,xm = 0; 141 | float temp_psumr; 142 | int i,j,m,flag,k; 143 | float *px; /* ptrs of respective P'(z) & Q'(z) */ 144 | float *qx; 145 | float *p; 146 | float *q; 147 | float *pt; /* ptr used for cheb_poly_eval() 148 | whether P' or Q' */ 149 | int roots=0; /* number of roots found */ 150 | float Q[order + 1]; 151 | float P[order + 1]; 152 | 153 | flag = 1; 154 | m = order/2; /* order of P'(z) & Q'(z) polynimials */ 155 | 156 | /* Allocate memory space for polynomials */ 157 | 158 | /* determine P'(z)'s and Q'(z)'s coefficients where 159 | P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */ 160 | 161 | px = P; /* initilaise ptrs */ 162 | qx = Q; 163 | p = px; 164 | q = qx; 165 | *px++ = 1.0; 166 | *qx++ = 1.0; 167 | for(i=1;i<=m;i++){ 168 | *px++ = a[i]+a[order+1-i]-*p++; 169 | *qx++ = a[i]-a[order+1-i]+*q++; 170 | } 171 | px = P; 172 | qx = Q; 173 | for(i=0;i= -1.0)){ 198 | xr = xl - delta ; /* interval spacing */ 199 | psumr = cheb_poly_eva(pt,xr,order);/* poly(xl-delta_x) */ 200 | temp_psumr = psumr; 201 | temp_xr = xr; 202 | 203 | /* if no sign change increment xr and re-evaluate 204 | poly(xr). Repeat til sign change. if a sign change has 205 | occurred the interval is bisected and then checked again 206 | for a sign change which determines in which interval the 207 | zero lies in. If there is no sign change between poly(xm) 208 | and poly(xl) set interval between xm and xr else set 209 | interval between xl and xr and repeat till root is located 210 | within the specified limits */ 211 | 212 | if(((psumr*psuml)<0.0) || (psumr == 0.0)){ 213 | roots++; 214 | 215 | psumm=psuml; 216 | for(k=0;k<=nb;k++){ 217 | xm = (xl+xr)/2; /* bisect the interval */ 218 | psumm=cheb_poly_eva(pt,xm,order); 219 | if(psumm*psuml>0.){ 220 | psuml=psumm; 221 | xl=xm; 222 | } 223 | else{ 224 | psumr=psumm; 225 | xr=xm; 226 | } 227 | } 228 | 229 | /* once zero is found, reset initial interval to xr */ 230 | freq[j] = (xm); 231 | xl = xm; 232 | flag = 0; /* reset flag for next search */ 233 | } 234 | else{ 235 | psuml=temp_psumr; 236 | xl=temp_xr; 237 | } 238 | } 239 | } 240 | 241 | /* convert from x domain to radians */ 242 | 243 | for(i=0; i. 29 | */ 30 | 31 | #ifndef __LSP__ 32 | #define __LSP__ 33 | 34 | int lpc_to_lsp (float *a, int lpcrdr, float *freq, int nb, float delta); 35 | void lsp_to_lpc(float *freq, float *ak, int lpcrdr); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /machdep.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: machdep.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: May 2 2013 6 | 7 | Machine dependant functions, e.g. profiling that requires access to a clock 8 | counter register. 9 | 10 | \*---------------------------------------------------------------------------*/ 11 | 12 | /* 13 | Copyright (C) 2013 David Rowe 14 | 15 | All rights reserved. 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU Lesser General Public License version 2.1, as 19 | published by the Free Software Foundation. This program is 20 | distributed in the hope that it will be useful, but WITHOUT ANY 21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 22 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23 | License for more details. 24 | 25 | You should have received a copy of the GNU Lesser General Public License 26 | along with this program; if not, see . 27 | */ 28 | 29 | #ifndef __MACHDEP__ 30 | #define __MACHDEP__ 31 | 32 | #ifdef PROFILE 33 | #define PROFILE_VAR(...) unsigned int __VA_ARGS__ 34 | #define PROFILE_SAMPLE(timestamp) timestamp = machdep_profile_sample() 35 | #define PROFILE_SAMPLE_AND_LOG(timestamp, prev_timestamp, label) \ 36 | timestamp = machdep_profile_sample_and_log(prev_timestamp, label) 37 | #define PROFILE_SAMPLE_AND_LOG2(prev_timestamp, label) \ 38 | machdep_profile_sample_and_log(prev_timestamp, label) 39 | #else 40 | #define PROFILE_VAR(...) 41 | #define PROFILE_SAMPLE(timestamp) 42 | #define PROFILE_SAMPLE_AND_LOG(timestamp, prev_timestamp, label) 43 | #define PROFILE_SAMPLE_AND_LOG2(prev_timestamp, label) 44 | #endif 45 | 46 | void machdep_profile_init(void); 47 | void machdep_profile_reset(void); 48 | unsigned int machdep_profile_sample(void); 49 | unsigned int machdep_profile_sample_and_log(unsigned int start, char s[]); 50 | void machdep_profile_print_logged_samples(void); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | //as usual... 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //internet 9 | #include 10 | #include 11 | 12 | //Codec2 13 | #include "codec2.h" 14 | 15 | //port 16 | uint16_t port_num=17000; //default port 17 | 18 | //UDP packet 19 | uint8_t bits[54]; 20 | 21 | //for reconstructed speech samples, 2x160 (2x20ms) 22 | uint16_t speech_buff[320]; 23 | 24 | //Codec2 structure 25 | struct CODEC2 *cod; 26 | 27 | //internet 28 | struct sockaddr_in si_me, si_other; 29 | int s, i, slen = sizeof(si_other) , rcv_len; 30 | 31 | //colors 32 | #define ANSI_COLOR_RED "\x1b[31m" 33 | #define ANSI_COLOR_GREEN "\x1b[32m" 34 | #define ANSI_COLOR_YELLOW "\x1b[33m" 35 | #define ANSI_COLOR_BLUE "\x1b[34m" 36 | #define ANSI_COLOR_MAGENTA "\x1b[35m" 37 | #define ANSI_COLOR_CYAN "\x1b[36m" 38 | #define ANSI_COLOR_RESET "\x1b[0m" 39 | 40 | //CRC 41 | uint16_t CRC_LUT[256]; 42 | uint16_t poly=0x5935; 43 | 44 | //test 45 | //FILE *fp; 46 | 47 | //stream info 48 | struct moip_packet 49 | { 50 | uint16_t sid; 51 | uint8_t src[10]; 52 | uint8_t dst[10]; 53 | uint16_t type; 54 | uint8_t nonce[14]; 55 | uint16_t fn; 56 | uint8_t payload[16]; 57 | uint16_t crc_udp; 58 | } packet; 59 | 60 | void CRC_Init(uint16_t *crc_table, uint16_t poly) 61 | { 62 | uint16_t remainder; 63 | 64 | for(uint16_t dividend=0; dividend<256; dividend++) 65 | { 66 | remainder=dividend<<8; 67 | 68 | for(uint8_t bit=8; bit>0; bit--) 69 | { 70 | if(remainder&(1<<15)) 71 | remainder=(remainder<<1)^poly; 72 | else 73 | remainder=(remainder<<1); 74 | } 75 | 76 | crc_table[dividend]=remainder; 77 | } 78 | } 79 | 80 | uint16_t CRC_M17(uint16_t* crc_table, const uint8_t* message, uint16_t nBytes) 81 | { 82 | uint8_t data; 83 | uint16_t remainder=0xFFFF; 84 | 85 | for(uint16_t byte=0; byte>8); 88 | remainder=crc_table[data]^(remainder<<8); 89 | } 90 | 91 | return(remainder); 92 | } 93 | 94 | uint8_t* decode_callsign_base40(uint64_t encoded, uint8_t *callsign) 95 | { 96 | if(encoded >= 262144000000000) 97 | { 98 | *callsign=0; 99 | return callsign; 100 | } 101 | 102 | uint8_t *p = callsign; 103 | 104 | for (; encoded>0; p++) 105 | { 106 | *p = "xABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded % 40]; 107 | encoded/=40; 108 | } 109 | 110 | *p = 0; 111 | 112 | return callsign; 113 | } 114 | 115 | int main(int argc, char *argv[]) 116 | { 117 | if(argc==2) 118 | { 119 | port_num=atoi(argv[1]); 120 | } 121 | else 122 | { 123 | fprintf(stderr, "Not enough args\n"); 124 | return 1; 125 | } 126 | 127 | //init 128 | cod = codec2_create(CODEC2_MODE_3200); 129 | memset(bits, 0, 54); 130 | memset(speech_buff, 0, 320); 131 | CRC_Init(CRC_LUT, poly); 132 | 133 | s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 134 | 135 | if(s==-1) 136 | { 137 | fprintf(stderr, "Socket error\n"); 138 | return 1; 139 | } 140 | 141 | //zero out the structure 142 | memset((char*)&si_me, 0, sizeof(si_me)); 143 | 144 | si_me.sin_family = AF_INET; 145 | si_me.sin_port = htons(port_num); 146 | si_me.sin_addr.s_addr = htonl(INADDR_ANY); 147 | 148 | if(bind(s, (struct sockaddr*)&si_me, sizeof(si_me))==-1) 149 | { 150 | fprintf(stderr, "Can't bind to port %d\n", port_num); 151 | return 1; 152 | } 153 | 154 | while(1) 155 | { 156 | //receive packet via UDP 157 | if((rcv_len=recvfrom(s, bits, 54, 0, (struct sockaddr*)&si_other, &slen))==-1) 158 | { 159 | fprintf(stderr, "What the hell?\n"); 160 | return 1; 161 | } 162 | 163 | if(rcv_len==54) 164 | { 165 | packet.sid=((uint16_t)bits[4]<<8)|bits[5]; 166 | uint64_t tmp; 167 | tmp=((uint64_t)bits[6]<<(5*8))|((uint64_t)bits[7]<<(4*8))|((uint64_t)bits[8]<<(3*8))|((uint64_t)bits[9]<<(2*8))|((uint64_t)bits[10]<<(1*8))|(uint64_t)bits[11]; 168 | decode_callsign_base40(tmp, packet.dst); 169 | tmp=((uint64_t)bits[12]<<(5*8))|((uint64_t)bits[13]<<(4*8))|((uint64_t)bits[14]<<(3*8))|((uint64_t)bits[15]<<(2*8))|((uint64_t)bits[16]<<(1*8))|(uint64_t)bits[17]; 170 | decode_callsign_base40(tmp, packet.src); 171 | packet.type=((uint16_t)bits[18]<<8)|bits[19]; 172 | 173 | memcpy(packet.nonce, &bits[20], 14); 174 | packet.fn=((uint16_t)bits[34]<<8)|(uint16_t)bits[35]; 175 | memcpy(packet.payload, &bits[36], 16); 176 | packet.crc_udp=((uint16_t)bits[52]<<8)|(uint16_t)bits[53]; 177 | uint16_t local_crc=CRC_M17(CRC_LUT, bits, 52); 178 | 179 | if(((packet.type>>1)&0b11)==0b10) //voice only 180 | { 181 | //reconstruct speech 182 | codec2_decode(cod, &speech_buff[0], &packet.payload[0]); 183 | codec2_decode(cod, &speech_buff[160], &packet.payload[8]); 184 | 185 | //send to stdout for playback 186 | for(uint16_t i=0; i<320*2; i++) 187 | { 188 | //signed 16bit, little endian 189 | if(!(i%2))//lsb 190 | printf("%c", (uint8_t)(speech_buff[i/2]&0xFF)); 191 | else 192 | printf("%c", (uint8_t)(speech_buff[i/2]>>8)); 193 | } 194 | 195 | fflush(stdout); 196 | } 197 | 198 | /*fp=fopen("out.raw", "a"); 199 | fwrite(speech_buff, 2, 160, fp); 200 | fclose(fp);*/ 201 | } 202 | } 203 | 204 | 205 | return 0; 206 | } 207 | -------------------------------------------------------------------------------- /mbest.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: mbest.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: Jan 2017 6 | 7 | Multistage vector quantiser search algorithm that keeps multiple 8 | candidates from each stage. 9 | 10 | \*---------------------------------------------------------------------------*/ 11 | 12 | /* 13 | Copyright David Rowe 2017 14 | 15 | All rights reserved. 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU Lesser General Public License version 2.1, as 19 | published by the Free Software Foundation. This program is 20 | distributed in the hope that it will be useful, but WITHOUT ANY 21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 22 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23 | License for more details. 24 | 25 | You should have received a copy of the GNU Lesser General Public License 26 | along with this program; if not, see . 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "mbest.h" 37 | 38 | struct MBEST *mbest_create(int entries) { 39 | int i,j; 40 | struct MBEST *mbest; 41 | 42 | assert(entries > 0); 43 | mbest = (struct MBEST *)malloc(sizeof(struct MBEST)); 44 | assert(mbest != NULL); 45 | 46 | mbest->entries = entries; 47 | mbest->list = (struct MBEST_LIST *)malloc(entries*sizeof(struct MBEST_LIST)); 48 | assert(mbest->list != NULL); 49 | 50 | for(i=0; ientries; i++) { 51 | for(j=0; jlist[i].index[j] = 0; 53 | mbest->list[i].error = 1E32; 54 | } 55 | 56 | return mbest; 57 | } 58 | 59 | 60 | void mbest_destroy(struct MBEST *mbest) { 61 | assert(mbest != NULL); 62 | free(mbest->list); 63 | free(mbest); 64 | } 65 | 66 | 67 | /*---------------------------------------------------------------------------*\ 68 | 69 | mbest_insert 70 | 71 | Insert the results of a vector to codebook entry comparison. The 72 | list is ordered in order or error, so those entries with the 73 | smallest error will be first on the list. 74 | 75 | \*---------------------------------------------------------------------------*/ 76 | 77 | void mbest_insert(struct MBEST *mbest, int index[], float error) { 78 | int i, j, found; 79 | struct MBEST_LIST *list = mbest->list; 80 | int entries = mbest->entries; 81 | 82 | found = 0; 83 | for(i=0; ii; j--) 87 | list[j] = list[j-1]; 88 | for(j=0; jentries; i++) { 101 | for(j=0; jlist[i].index[j]); 103 | fprintf(stderr, " %f\n", mbest->list[i].error); 104 | } 105 | } 106 | #endif 107 | 108 | 109 | /*---------------------------------------------------------------------------*\ 110 | 111 | mbest_search 112 | 113 | Searches vec[] to a codebbook of vectors, and maintains a list of the mbest 114 | closest matches. 115 | 116 | \*---------------------------------------------------------------------------*/ 117 | 118 | void mbest_search( 119 | const float *cb, /* VQ codebook to search */ 120 | float vec[], /* target vector */ 121 | float w[], /* weighting vector */ 122 | int k, /* dimension of vector */ 123 | int m, /* number on entries in codebook */ 124 | struct MBEST *mbest, /* list of closest matches */ 125 | int index[] /* indexes that lead us here */ 126 | ) 127 | { 128 | float e; 129 | int i,j; 130 | float diff; 131 | 132 | for(j=0; j. 27 | 28 | */ 29 | 30 | #ifndef __MBEST__ 31 | #define __MBEST__ 32 | 33 | #define MBEST_STAGES 4 34 | 35 | struct MBEST_LIST { 36 | int index[MBEST_STAGES]; /* index of each stage that lead us to this error */ 37 | float error; 38 | }; 39 | 40 | struct MBEST { 41 | int entries; /* number of entries in mbest list */ 42 | struct MBEST_LIST *list; 43 | }; 44 | 45 | struct MBEST *mbest_create(int entries); 46 | void mbest_destroy(struct MBEST *mbest); 47 | void mbest_insert(struct MBEST *mbest, int index[], float error); 48 | void mbest_search(const float *cb, float vec[], float w[], int k, int m, struct MBEST *mbest, int index[]); 49 | 50 | // #define MBEST_PRINT_OUT 51 | #ifdef MBEST_PRINT_OUT 52 | #define MBEST_PRINT(a,b) mbest_print((a),(b)) 53 | #else 54 | #define MBEST_PRINT(a,b) 55 | #endif 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /modem_stats.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: modem_stats.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: June 2015 6 | 7 | Common functions for returning demod stats from fdmdv and cohpsk modems. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2015 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #include 29 | #include 30 | #include "modem_stats.h" 31 | #include "codec2_fdmdv.h" 32 | 33 | void modem_stats_open(struct MODEM_STATS *f) 34 | { 35 | int i; 36 | 37 | for(i=0; i<2*MODEM_STATS_NSPEC; i++) 38 | f->fft_buf[i] = 0.0; 39 | f->fft_cfg = kiss_fft_alloc (2*MODEM_STATS_NSPEC, 0, NULL, NULL); 40 | assert(f->fft_cfg != NULL); 41 | } 42 | 43 | void modem_stats_close(struct MODEM_STATS *f) 44 | { 45 | KISS_FFT_FREE(f->fft_cfg); 46 | } 47 | 48 | /*---------------------------------------------------------------------------*\ 49 | 50 | FUNCTION....: modem_stats_get_rx_spectrum() 51 | AUTHOR......: David Rowe 52 | DATE CREATED: 9 June 2012 53 | 54 | Returns the MODEM_STATS_NSPEC point magnitude spectrum of the rx signal in 55 | dB. The spectral samples are scaled so that 0dB is the peak, a good 56 | range for plotting is 0 to -40dB. 57 | 58 | Note only the real part of the complex input signal is used at 59 | present. A complex variable is used for input for compatability 60 | with the other rx signal procesing. 61 | 62 | Successive calls can be used to build up a waterfall or spectrogram 63 | plot, by mapping the received levels to colours. 64 | 65 | The time-frequency resolution of the spectrum can be adjusted by varying 66 | MODEM_STATS_NSPEC. Note that a 2* MODEM_STATS_NSPEC size FFT is reqd to get 67 | MODEM_STATS_NSPEC output points. MODEM_STATS_NSPEC must be a power of 2. 68 | 69 | See octave/tget_spec.m for a demo real time spectral display using 70 | Octave. This demo averages the output over time to get a smoother 71 | display: 72 | 73 | av = 0.9*av + 0.1*mag_dB 74 | 75 | \*---------------------------------------------------------------------------*/ 76 | 77 | void modem_stats_get_rx_spectrum(struct MODEM_STATS *f, float mag_spec_dB[], COMP rx_fdm[], int nin) 78 | { 79 | int i,j; 80 | COMP fft_in[2*MODEM_STATS_NSPEC]; 81 | COMP fft_out[2*MODEM_STATS_NSPEC]; 82 | float full_scale_dB; 83 | 84 | /* update buffer of input samples */ 85 | 86 | for(i=0; i<2*MODEM_STATS_NSPEC-nin; i++) 87 | f->fft_buf[i] = f->fft_buf[i+nin]; 88 | for(j=0; jfft_buf[i] = rx_fdm[j].real; 90 | assert(i == 2*MODEM_STATS_NSPEC); 91 | 92 | /* window and FFT */ 93 | 94 | for(i=0; i<2*MODEM_STATS_NSPEC; i++) { 95 | #define M_PI 3.14159265358979323846 96 | fft_in[i].real = f->fft_buf[i] * (0.5 - 0.5*cosf((float)i*2.0*M_PI/(2*MODEM_STATS_NSPEC))); 97 | fft_in[i].imag = 0.0; 98 | } 99 | 100 | kiss_fft(f->fft_cfg, (kiss_fft_cpx *)fft_in, (kiss_fft_cpx *)fft_out); 101 | 102 | /* FFT scales up a signal of level 1 FDMDV_NSPEC */ 103 | 104 | full_scale_dB = 20*log10(MODEM_STATS_NSPEC*FDMDV_SCALE); 105 | 106 | /* scale and convert to dB */ 107 | 108 | for(i=0; i. 26 | */ 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | #ifndef __MODEM_STATS__ 33 | #define __MODEM_STATS__ 34 | 35 | #include "comp.h" 36 | #include "kiss_fft.h" 37 | 38 | #define MODEM_STATS_NC_MAX 20 39 | #define MODEM_STATS_NR_MAX 8 40 | #define MODEM_STATS_ET_MAX 8 41 | #define MODEM_STATS_NSPEC 512 42 | #define MODEM_STATS_MAX_F_HZ 4000 43 | #define MODEM_STATS_MAX_F_EST 4 44 | 45 | struct MODEM_STATS { 46 | int Nc; 47 | float snr_est; /* estimated SNR of rx signal in dB (3 kHz noise BW) */ 48 | COMP rx_symbols[MODEM_STATS_NR_MAX][MODEM_STATS_NC_MAX+1]; 49 | /* latest received symbols, for scatter plot */ 50 | int nr; /* number of rows in rx_symbols */ 51 | int sync; /* demod sync state */ 52 | float foff; /* estimated freq offset in Hz */ 53 | float rx_timing; /* estimated optimum timing offset in samples */ 54 | float clock_offset; /* Estimated tx/rx sample clock offset in ppm */ 55 | 56 | /* eye diagram traces */ 57 | /* Eye diagram plot -- first dim is trace number, second is the trace idx */ 58 | float rx_eye[MODEM_STATS_ET_MAX][80]; 59 | int neyetr; /* How many eye traces are plotted */ 60 | int neyesamp; /* How many samples in the eye diagram */ 61 | 62 | /* optional for FSK modems - est tone freqs */ 63 | 64 | float f_est[MODEM_STATS_MAX_F_EST]; 65 | 66 | /* Buf for FFT/waterfall */ 67 | 68 | float fft_buf[2*MODEM_STATS_NSPEC]; 69 | kiss_fft_cfg fft_cfg; 70 | }; 71 | 72 | void modem_stats_open(struct MODEM_STATS *f); 73 | void modem_stats_close(struct MODEM_STATS *f); 74 | void modem_stats_get_rx_spectrum(struct MODEM_STATS *f, float mag_spec_dB[], COMP rx_fdm[], int nin); 75 | 76 | #endif 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /mpdecode_core.h: -------------------------------------------------------------------------------- 1 | /* 2 | FILE...: mpdecode_core.h 3 | AUTHOR.: David Rowe 4 | CREATED: Sep 2016 5 | 6 | C-callable core functions for MpDecode, so they can be used for 7 | Octave and C programs. Also some convenience functions to help use 8 | the C-callable LDPC decoder in C programs. 9 | */ 10 | 11 | #ifndef __MPDECODE_CORE__ 12 | #define __MPDECODE_CORE__ 13 | 14 | #include "comp.h" 15 | 16 | struct LDPC { 17 | int max_iter; 18 | int dec_type; 19 | int q_scale_factor; 20 | int r_scale_factor; 21 | int CodeLength; 22 | int NumberParityBits; 23 | int NumberRowsHcols; 24 | int max_row_weight; 25 | int max_col_weight; 26 | int data_bits_per_frame; 27 | int coded_bits_per_frame; 28 | int coded_syms_per_frame; 29 | double *H_rows; 30 | double *H_cols; 31 | }; 32 | 33 | void encode(struct LDPC *ldpc, unsigned char ibits[], unsigned char pbits[]); 34 | 35 | int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[], int *parityCheckCount); 36 | 37 | void sd_to_llr(double llr[], double sd[], int n); 38 | 39 | void Demod2D(double symbol_likelihood[], COMP r[], COMP S_matrix[], float EsNo, float fading[], float mean_amp, int number_symbols); 40 | void Somap(double bit_likelihood[], double symbol_likelihood[], int number_symbols); 41 | void symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, float mean_amp, int nsyms); 42 | 43 | struct v_node { 44 | int degree; 45 | float initial_value; 46 | int *index; /* the index of a c_node it is connected to */ 47 | int *socket; /* socket number at the c_node */ 48 | float *message; 49 | int *sign; 50 | }; 51 | 52 | struct c_node { 53 | int degree; 54 | int *index; 55 | float *message; 56 | int *socket; /* socket number at the v_node */ 57 | }; 58 | 59 | void init_c_v_nodes(struct c_node *c_nodes, 60 | int shift, 61 | int NumberParityBits, 62 | int max_row_weight, 63 | double *H_rows, 64 | int H1, 65 | int CodeLength, 66 | struct v_node *v_nodes, 67 | int NumberRowsHcols, 68 | double *H_cols, 69 | int max_col_weight, 70 | int dec_type, 71 | double *input); 72 | 73 | void ApproximateMinStar( int BitErrors[], 74 | int DecodedBits[], 75 | struct c_node c_nodes[], 76 | struct v_node v_nodes[], 77 | int CodeLength, 78 | int NumberParityBits, 79 | int max_iter ); 80 | 81 | void MinSum( int BitErrors[], 82 | int DecodedBits[], 83 | struct c_node c_nodes[], 84 | struct v_node v_nodes[], 85 | int CodeLength, 86 | int NumberParityBits, 87 | int max_iter, 88 | float r_scale_factor, 89 | float q_scale_factor, 90 | int data[] ); 91 | 92 | 93 | void SumProduct( int BitErrors[], 94 | int DecodedBits[], 95 | struct c_node c_nodes[], 96 | struct v_node v_nodes[], 97 | int CodeLength, 98 | int NumberParityBits, 99 | int max_iter, 100 | float r_scale_factor, 101 | float q_scale_factor, 102 | int data[]); 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /newamp1.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: newamp1.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: Jan 2017 6 | 7 | Quantisation functions for the sinusoidal coder, using "newamp1" 8 | algorithm that resamples variable rate L [Am} to a fixed rate K then 9 | VQs. 10 | 11 | \*---------------------------------------------------------------------------*/ 12 | 13 | /* 14 | Copyright David Rowe 2017 15 | 16 | All rights reserved. 17 | 18 | This program is free software; you can redistribute it and/or modify 19 | it under the terms of the GNU Lesser General Public License version 2.1, as 20 | published by the Free Software Foundation. This program is 21 | distributed in the hope that it will be useful, but WITHOUT ANY 22 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 24 | License for more details. 25 | 26 | You should have received a copy of the GNU Lesser General Public License 27 | along with this program; if not, see . 28 | */ 29 | 30 | #ifndef __NEWAMP1__ 31 | #define __NEWAMP1__ 32 | 33 | #define NEWAMP1_N_INDEXES 4 /* Number of indexes to pack: vq1, vq2, energy, Wo */ 34 | #define NEWAMP1_PHASE_NFFT 128 /* size of FFT used for phase synthesis */ 35 | #define NEWAMP1_K 20 /* rate K vector length */ 36 | 37 | #include "codec2_fft.h" 38 | #include "comp.h" 39 | 40 | void interp_para(float y[], float xp[], float yp[], int np, float x[], int n); 41 | float ftomel(float fHz); 42 | void mel_sample_freqs_kHz(float rate_K_sample_freqs_kHz[], int K, float mel_start, float mel_end); 43 | void resample_const_rate_f(C2CONST *c2const, MODEL *model, float rate_K_vec[], float rate_K_sample_freqs_kHz[], int K); 44 | float rate_K_mbest_encode(int *indexes, float *x, float *xq, int ndim, int mbest_entries); 45 | void post_filter_newamp1(float vec[], float sample_freq_kHz[], int K, float pf_gain); 46 | void interp_Wo_v(float Wo_[], int L_[], int voicing_[], float Wo1, float Wo2, int voicing1, int voicing2); 47 | void resample_rate_L(C2CONST *c2const, MODEL *model, float rate_K_vec[], float rate_K_sample_freqs_kHz[], int K); 48 | void determine_phase(C2CONST *c2const, COMP H[], MODEL *model, int Nfft, codec2_fft_cfg fwd_cfg, codec2_fft_cfg inv_cfg); 49 | void newamp1_model_to_indexes(C2CONST *c2const, 50 | int indexes[], 51 | MODEL *model, 52 | float rate_K_vec[], 53 | float rate_K_sample_freqs_kHz[], 54 | int K, 55 | float *mean, 56 | float rate_K_vec_no_mean[], 57 | float rate_K_vec_no_mean_[] 58 | ); 59 | void newamp1_indexes_to_rate_K_vec(float rate_K_vec_[], 60 | float rate_K_vec_no_mean_[], 61 | float rate_K_sample_freqs_kHz[], 62 | int K, 63 | float *mean_, 64 | int indexes[]); 65 | void newamp1_interpolate(float interpolated_surface_[], float left_vec[], float right_vec[], int K); 66 | 67 | void newamp1_indexes_to_model(C2CONST *c2const, 68 | MODEL model_[], 69 | COMP H[], 70 | float interpolated_surface_[], 71 | float prev_rate_K_vec_[], 72 | float *Wo_left, 73 | int *voicing_left, 74 | float rate_K_sample_freqs_kHz[], 75 | int K, 76 | codec2_fft_cfg fwd_cfg, 77 | codec2_fft_cfg inv_cfg, 78 | int indexes[]); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /nlp.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: nlp.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 23/3/93 6 | 7 | Non Linear Pitch (NLP) estimation functions. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef __NLP__ 29 | #define __NLP__ 30 | 31 | #include "comp.h" 32 | 33 | void *nlp_create(C2CONST *c2const); 34 | void nlp_destroy(void *nlp_state); 35 | float nlp(void *nlp_state, float Sn[], int n, 36 | float *pitch_samples, COMP Sw[], COMP W[], float *prev_f0); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ofdm_bpf_coeff.h: -------------------------------------------------------------------------------- 1 | /* 1000 - 2000 Hz FIR filter coeffs */ 2 | /* Generated by make_ofdm_bpf() in ofdm_lib.m */ 3 | 4 | #define OFDM_BPF_N 100 5 | 6 | float ofdm_bpf_coeff[]={ 7 | -0.000130, 8 | 0.000145, 9 | 0.000534, 10 | 0.000237, 11 | -0.000425, 12 | -0.000414, 13 | -0.000000, 14 | -0.000271, 15 | -0.000577, 16 | 0.000509, 17 | 0.001703, 18 | 0.000688, 19 | -0.001054, 20 | -0.000665, 21 | -0.000000, 22 | -0.001797, 23 | -0.002415, 24 | 0.001735, 25 | 0.004932, 26 | 0.001650, 27 | -0.001795, 28 | 0.000266, 29 | 0.000000, 30 | -0.006788, 31 | -0.007186, 32 | 0.004372, 33 | 0.010484, 34 | 0.002692, 35 | -0.000892, 36 | 0.005638, 37 | 0.000000, 38 | -0.018730, 39 | -0.016849, 40 | 0.008829, 41 | 0.017210, 42 | 0.002427, 43 | 0.005928, 44 | 0.022889, 45 | 0.000000, 46 | -0.046278, 47 | -0.036943, 48 | 0.016698, 49 | 0.022813, 50 | -0.003850, 51 | 0.037536, 52 | 0.094889, 53 | 0.000000, 54 | -0.186545, 55 | -0.170197, 56 | 0.101783, 57 | 0.275749, 58 | 0.101783, 59 | -0.170197, 60 | -0.186545, 61 | 0.000000, 62 | 0.094889, 63 | 0.037536, 64 | -0.003850, 65 | 0.022813, 66 | 0.016698, 67 | -0.036943, 68 | -0.046278, 69 | 0.000000, 70 | 0.022889, 71 | 0.005928, 72 | 0.002427, 73 | 0.017210, 74 | 0.008829, 75 | -0.016849, 76 | -0.018730, 77 | 0.000000, 78 | 0.005638, 79 | -0.000892, 80 | 0.002692, 81 | 0.010484, 82 | 0.004372, 83 | -0.007186, 84 | -0.006788, 85 | 0.000000, 86 | 0.000266, 87 | -0.001795, 88 | 0.001650, 89 | 0.004932, 90 | 0.001735, 91 | -0.002415, 92 | -0.001797, 93 | -0.000000, 94 | -0.000665, 95 | -0.001054, 96 | 0.000688, 97 | 0.001703, 98 | 0.000509, 99 | -0.000577, 100 | -0.000271, 101 | -0.000000, 102 | -0.000414, 103 | -0.000425, 104 | 0.000237, 105 | 0.000534, 106 | 0.000145 107 | }; -------------------------------------------------------------------------------- /ofdm_internal.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: ofdm_internal.h 4 | AUTHORS.....: David Rowe & Steve Sampson 5 | DATE CREATED: June 2017 6 | 7 | OFDM Internal definitions. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2017 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef OFDM_INTERNAL_H 29 | #define OFDM_INTERNAL_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "codec2_ofdm.h" 40 | 41 | #ifndef M_PI 42 | #define M_PI 3.14159265358979323846f /* math constant */ 43 | #endif 44 | 45 | #define TAU (2.0f * M_PI) /* mathematical constant */ 46 | 47 | #define OFDM_NC 17 /* N Carriers */ 48 | #define OFDM_TS 0.018f /* Symbol time */ 49 | #define OFDM_RS (1.0f / OFDM_TS) /* Symbol rate */ 50 | #define OFDM_FS 8000.0f /* Sample rate */ 51 | #define OFDM_BPS 2 /* Bits per symbol */ 52 | #define OFDM_TCP 0.002f /* Cyclic prefix duration */ 53 | #define OFDM_NS 8 /* NS-1 data symbols between pilots */ 54 | #define OFDM_CENTRE 1500.0f /* Center frequency */ 55 | 56 | /* To prevent C99 warning */ 57 | 58 | #define OFDM_M 144 /* duration of each symbol in samples */ 59 | #define OFDM_NCP 16 /* duration of CP in samples */ 60 | 61 | #ifdef OLD_STYLE 62 | /* This will produce a warning in C99 as (int) makes these variable */ 63 | 64 | #define OFDM_M ((int)(OFDM_FS / OFDM_RS)) 65 | #define OFDM_NCP ((int)(OFDM_TCP * OFDM_FS)) 66 | #endif 67 | 68 | #define OFDM_INVERSE_M (1.0f / (float) OFDM_M) 69 | 70 | /* number of symbols we estimate fine timing over */ 71 | #define OFDM_FTWINDOWWIDTH 11 72 | /* Bits per frame (duh) */ 73 | #define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NC * OFDM_BPS)) 74 | /* Rows per frame with data symbols */ 75 | #define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NC * OFDM_BPS)) 76 | /* Samps per frame */ 77 | #define OFDM_SAMPLESPERFRAME (OFDM_NS * (OFDM_M + OFDM_NCP)) 78 | 79 | #define OFDM_MAX_SAMPLESPERFRAME (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP)/4) 80 | #define OFDM_RXBUF (3 * OFDM_SAMPLESPERFRAME + 3 * (OFDM_M + OFDM_NCP)) 81 | 82 | /* See 700D Part 4 Acquisition blog post and ofdm_dev.m routinesfor how this was set */ 83 | 84 | #define OFDM_TIMING_MX_THRESH 0.35 85 | 86 | /* reserve 4 bits/frame for auxillary text information */ 87 | 88 | #define OFDM_NTXTBITS 4 89 | 90 | /* Unique word, used for positive indication of lock */ 91 | 92 | #define OFDM_NUWBITS ((OFDM_NS-1)*OFDM_BPS - OFDM_NTXTBITS) 93 | 94 | #define OFDM_STATE_STR 16 95 | 96 | /* Dummy struct for now, will contain constant configuration for OFDM modem */ 97 | struct OFDM_CONFIG{ 98 | int a; 99 | }; 100 | 101 | 102 | struct OFDM { 103 | struct OFDM_CONFIG config; 104 | float foff_est_gain; 105 | float foff_est_hz; 106 | 107 | int verbose; 108 | int sample_point; 109 | int timing_est; 110 | int timing_valid; 111 | float timing_mx; 112 | float coarse_foff_est_hz; 113 | int nin; 114 | 115 | bool timing_en; 116 | bool foff_est_en; 117 | bool phase_est_en; 118 | bool tx_bpf_en; 119 | 120 | complex float pilot_samples[OFDM_M + OFDM_NCP]; 121 | float timing_norm; 122 | complex float W[OFDM_NC + 2][OFDM_M]; 123 | complex float rxbuf[OFDM_RXBUF]; 124 | complex float pilots[OFDM_NC + 2]; 125 | complex float *tx_bpf_buf; 126 | 127 | /* Demodulator data */ 128 | 129 | complex float rx_sym[OFDM_NS + 3][OFDM_NC + 2]; 130 | complex float rx_np[OFDM_ROWSPERFRAME * OFDM_NC]; 131 | float rx_amp[OFDM_ROWSPERFRAME * OFDM_NC]; 132 | float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NC]; 133 | float sig_var; 134 | float noise_var; 135 | float mean_amp; 136 | complex float foff_metric; 137 | 138 | /* modem sync state machine */ 139 | 140 | int tx_uw[OFDM_NUWBITS]; 141 | char sync_state[OFDM_STATE_STR]; 142 | char last_sync_state[OFDM_STATE_STR]; 143 | int uw_errors; 144 | int sync_counter; 145 | int frame_count; 146 | int sync_start; 147 | int sync_end; 148 | int sync_mode; 149 | 150 | /* interleaver sync state machine */ 151 | 152 | char sync_state_interleaver[OFDM_STATE_STR]; 153 | char last_sync_state_interleaver[OFDM_STATE_STR]; 154 | int frame_count_interleaver; 155 | }; 156 | 157 | 158 | /* function headers exposed for LDPC work */ 159 | 160 | complex float qpsk_mod(int *); 161 | void qpsk_demod(complex float, int *); 162 | void ofdm_txframe(struct OFDM *, complex float tx_samples[OFDM_SAMPLESPERFRAME], complex float tx_symbols_lin[]); 163 | void ofdm_assemble_modem_frame(complex float modem_frame[], COMP payload_syms[], uint8_t txt_bits[]); 164 | void ofdm_disassemble_modem_frame(struct OFDM *ofdm, 165 | int rx_uw[], 166 | COMP codeword_syms[], 167 | float codeword_amps[], 168 | short txt_bits[]); 169 | #ifdef __cplusplus 170 | } 171 | #endif 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /os.h: -------------------------------------------------------------------------------- 1 | /* Generate using fir1(47,1/2) in Octave */ 2 | 3 | static const float fdmdv_os_filter[]= { 4 | -0.0008215855034550382, 5 | -0.0007833023901802921, 6 | 0.001075563790768233, 7 | 0.001199092367787555, 8 | -0.001765309502928316, 9 | -0.002055372115328064, 10 | 0.002986877604154257, 11 | 0.003462567920638414, 12 | -0.004856570111126334, 13 | -0.005563143845031497, 14 | 0.007533613299748122, 15 | 0.008563932468880897, 16 | -0.01126857129039911, 17 | -0.01280782411693687, 18 | 0.01651443896361847, 19 | 0.01894875110322284, 20 | -0.02421604439474981, 21 | -0.02845107338464062, 22 | 0.03672973563400258, 23 | 0.04542046150312214, 24 | -0.06189165826716491, 25 | -0.08721876380763803, 26 | 0.1496157094199961, 27 | 0.4497962274137046, 28 | 0.4497962274137046, 29 | 0.1496157094199961, 30 | -0.08721876380763803, 31 | -0.0618916582671649, 32 | 0.04542046150312216, 33 | 0.03672973563400257, 34 | -0.02845107338464062, 35 | -0.02421604439474984, 36 | 0.01894875110322284, 37 | 0.01651443896361848, 38 | -0.01280782411693687, 39 | -0.0112685712903991, 40 | 0.008563932468880899, 41 | 0.007533613299748123, 42 | -0.005563143845031501, 43 | -0.004856570111126346, 44 | 0.003462567920638419, 45 | 0.002986877604154259, 46 | -0.002055372115328063, 47 | -0.001765309502928318, 48 | 0.001199092367787557, 49 | 0.001075563790768233, 50 | -0.0007833023901802925, 51 | -0.0008215855034550383 52 | }; 53 | 54 | -------------------------------------------------------------------------------- /pack.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2010 Perens LLC 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License version 2.1, as 8 | published by the Free Software Foundation. This program is 9 | distributed in the hope that it will be useful, but WITHOUT ANY 10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 12 | License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program; if not, see . 16 | */ 17 | 18 | #include "defines.h" 19 | #include "quantise.h" 20 | #include 21 | 22 | /* Compile-time constants */ 23 | /* Size of unsigned char in bits. Assumes 8 bits-per-char. */ 24 | static const unsigned int WordSize = 8; 25 | 26 | /* Mask to pick the bit component out of bitIndex. */ 27 | static const unsigned int IndexMask = 0x7; 28 | 29 | /* Used to pick the word component out of bitIndex. */ 30 | static const unsigned int ShiftRight = 3; 31 | 32 | /** Pack a bit field into a bit string, encoding the field in Gray code. 33 | * 34 | * The output is an array of unsigned char data. The fields are efficiently 35 | * packed into the bit string. The Gray coding is a naive attempt to reduce 36 | * the effect of single-bit errors, we expect to do a better job as the 37 | * codec develops. 38 | * 39 | * This code would be simpler if it just set one bit at a time in the string, 40 | * but would hit the same cache line more often. I'm not sure the complexity 41 | * gains us anything here. 42 | * 43 | * Although field is currently of int type rather than unsigned for 44 | * compatibility with the rest of the code, indices are always expected to 45 | * be >= 0. 46 | */ 47 | void 48 | pack( 49 | unsigned char * bitArray, /* The output bit string. */ 50 | unsigned int * bitIndex, /* Index into the string in BITS, not bytes.*/ 51 | int field, /* The bit field to be packed. */ 52 | unsigned int fieldWidth/* Width of the field in BITS, not bytes. */ 53 | ) 54 | { 55 | pack_natural_or_gray(bitArray, bitIndex, field, fieldWidth, 1); 56 | } 57 | 58 | void 59 | pack_natural_or_gray( 60 | unsigned char * bitArray, /* The output bit string. */ 61 | unsigned int * bitIndex, /* Index into the string in BITS, not bytes.*/ 62 | int field, /* The bit field to be packed. */ 63 | unsigned int fieldWidth,/* Width of the field in BITS, not bytes. */ 64 | unsigned int gray /* non-zero for gray coding */ 65 | ) 66 | { 67 | if (gray) { 68 | /* Convert the field to Gray code */ 69 | field = (field >> 1) ^ field; 70 | } 71 | 72 | do { 73 | unsigned int bI = *bitIndex; 74 | unsigned int bitsLeft = WordSize - (bI & IndexMask); 75 | unsigned int sliceWidth = 76 | bitsLeft < fieldWidth ? bitsLeft : fieldWidth; 77 | unsigned int wordIndex = bI >> ShiftRight; 78 | 79 | bitArray[wordIndex] |= 80 | ((unsigned char)((field >> (fieldWidth - sliceWidth)) 81 | << (bitsLeft - sliceWidth))); 82 | 83 | *bitIndex = bI + sliceWidth; 84 | fieldWidth -= sliceWidth; 85 | } while ( fieldWidth != 0 ); 86 | } 87 | 88 | /** Unpack a field from a bit string, converting from Gray code to binary. 89 | * 90 | */ 91 | int 92 | unpack( 93 | const unsigned char * bitArray, /* The input bit string. */ 94 | unsigned int * bitIndex, /* Index into the string in BITS, not bytes.*/ 95 | unsigned int fieldWidth/* Width of the field in BITS, not bytes. */ 96 | ) 97 | { 98 | return unpack_natural_or_gray(bitArray, bitIndex, fieldWidth, 1); 99 | } 100 | 101 | /** Unpack a field from a bit string, to binary, optionally using 102 | * natural or Gray code. 103 | * 104 | */ 105 | int 106 | unpack_natural_or_gray( 107 | const unsigned char * bitArray, /* The input bit string. */ 108 | unsigned int * bitIndex, /* Index into the string in BITS, not bytes.*/ 109 | unsigned int fieldWidth,/* Width of the field in BITS, not bytes. */ 110 | unsigned int gray /* non-zero for Gray coding */ 111 | ) 112 | { 113 | unsigned int field = 0; 114 | unsigned int t; 115 | 116 | do { 117 | unsigned int bI = *bitIndex; 118 | unsigned int bitsLeft = WordSize - (bI & IndexMask); 119 | unsigned int sliceWidth = 120 | bitsLeft < fieldWidth ? bitsLeft : fieldWidth; 121 | 122 | field |= (((bitArray[bI >> ShiftRight] >> (bitsLeft - sliceWidth)) & ((1 << sliceWidth) - 1)) << (fieldWidth - sliceWidth)); 123 | 124 | *bitIndex = bI + sliceWidth; 125 | fieldWidth -= sliceWidth; 126 | } while ( fieldWidth != 0 ); 127 | 128 | if (gray) { 129 | /* Convert from Gray code to binary. Works for maximum 8-bit fields. */ 130 | t = field ^ (field >> 8); 131 | t ^= (t >> 4); 132 | t ^= (t >> 2); 133 | t ^= (t >> 1); 134 | } 135 | else { 136 | t = field; 137 | } 138 | 139 | return t; 140 | } 141 | -------------------------------------------------------------------------------- /phase.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: phase.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 1/2/09 6 | 7 | Functions for modelling and synthesising phase. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not,see . 26 | */ 27 | 28 | #include "defines.h" 29 | #include "phase.h" 30 | #include "kiss_fft.h" 31 | #include "comp.h" 32 | #include "comp_prim.h" 33 | #include "sine.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | /*---------------------------------------------------------------------------*\ 42 | 43 | sample_phase() 44 | 45 | Samples phase at centre of each harmonic from and array of FFT_ENC 46 | DFT samples. 47 | 48 | \*---------------------------------------------------------------------------*/ 49 | 50 | void sample_phase(MODEL *model, 51 | COMP H[], 52 | COMP A[] /* LPC analysis filter in freq domain */ 53 | ) 54 | { 55 | int m, b; 56 | float r; 57 | 58 | r = TWO_PI/(FFT_ENC); 59 | 60 | /* Sample phase at harmonics */ 61 | 62 | for(m=1; m<=model->L; m++) { 63 | b = (int)(m*model->Wo/r + 0.5); 64 | H[m] = cconj(A[b]); /* synth filter 1/A is opposite phase to analysis filter */ 65 | } 66 | } 67 | 68 | 69 | /*---------------------------------------------------------------------------*\ 70 | 71 | phase_synth_zero_order() 72 | 73 | Synthesises phases based on SNR and a rule based approach. No phase 74 | parameters are required apart from the SNR (which can be reduced to a 75 | 1 bit V/UV decision per frame). 76 | 77 | The phase of each harmonic is modelled as the phase of a synthesis 78 | filter excited by an impulse. In many Codec 2 modes the synthesis 79 | filter is a LPC filter. Unlike the first order model the position 80 | of the impulse is not transmitted, so we create an excitation pulse 81 | train using a rule based approach. 82 | 83 | Consider a pulse train with a pulse starting time n=0, with pulses 84 | repeated at a rate of Wo, the fundamental frequency. A pulse train 85 | in the time domain is equivalent to harmonics in the frequency 86 | domain. We can make an excitation pulse train using a sum of 87 | sinsusoids: 88 | 89 | for(m=1; m<=L; m++) 90 | ex[n] = cos(m*Wo*n) 91 | 92 | Note: the Octave script ../octave/phase.m is an example of this if 93 | you would like to try making a pulse train. 94 | 95 | The phase of each excitation harmonic is: 96 | 97 | arg(E[m]) = mWo 98 | 99 | where E[m] are the complex excitation (freq domain) samples, 100 | arg(x), just returns the phase of a complex sample x. 101 | 102 | As we don't transmit the pulse position for this model, we need to 103 | synthesise it. Now the excitation pulses occur at a rate of Wo. 104 | This means the phase of the first harmonic advances by N_SAMP samples 105 | over a synthesis frame of N_SAMP samples. For example if Wo is pi/20 106 | (200 Hz), then over a 10ms frame (N_SAMP=80 samples), the phase of the 107 | first harmonic would advance (pi/20)*80 = 4*pi or two complete 108 | cycles. 109 | 110 | We generate the excitation phase of the fundamental (first 111 | harmonic): 112 | 113 | arg[E[1]] = Wo*N_SAMP; 114 | 115 | We then relate the phase of the m-th excitation harmonic to the 116 | phase of the fundamental as: 117 | 118 | arg(E[m]) = m*arg(E[1]) 119 | 120 | This E[m] then gets passed through the LPC synthesis filter to 121 | determine the final harmonic phase. 122 | 123 | Comparing to speech synthesised using original phases: 124 | 125 | - Through headphones speech synthesised with this model is not as 126 | good. Through a loudspeaker it is very close to original phases. 127 | 128 | - If there are voicing errors, the speech can sound clicky or 129 | staticy. If V speech is mistakenly declared UV, this model tends to 130 | synthesise impulses or clicks, as there is usually very little shift or 131 | dispersion through the LPC synthesis filter. 132 | 133 | - When combined with LPC amplitude modelling there is an additional 134 | drop in quality. I am not sure why, theory is interformant energy 135 | is raised making any phase errors more obvious. 136 | 137 | NOTES: 138 | 139 | 1/ This synthesis model is effectively the same as a simple LPC-10 140 | vocoders, and yet sounds much better. Why? Conventional wisdom 141 | (AMBE, MELP) says mixed voicing is required for high quality 142 | speech. 143 | 144 | 2/ I am pretty sure the Lincoln Lab sinusoidal coding guys (like xMBE 145 | also from MIT) first described this zero phase model, I need to look 146 | up the paper. 147 | 148 | 3/ Note that this approach could cause some discontinuities in 149 | the phase at the edge of synthesis frames, as no attempt is made 150 | to make sure that the phase tracks are continuous (the excitation 151 | phases are continuous, but not the final phases after filtering 152 | by the LPC spectra). Technically this is a bad thing. However 153 | this may actually be a good thing, disturbing the phase tracks a 154 | bit. More research needed, e.g. test a synthesis model that adds 155 | a small delta-W to make phase tracks line up for voiced 156 | harmonics. 157 | 158 | \*---------------------------------------------------------------------------*/ 159 | 160 | void phase_synth_zero_order( 161 | int n_samp, 162 | MODEL *model, 163 | float *ex_phase, /* excitation phase of fundamental */ 164 | COMP H[] /* L synthesis filter freq domain samples */ 165 | 166 | ) 167 | { 168 | int m; 169 | float new_phi; 170 | COMP Ex[MAX_AMP+1]; /* excitation samples */ 171 | COMP A_[MAX_AMP+1]; /* synthesised harmonic samples */ 172 | 173 | /* 174 | Update excitation fundamental phase track, this sets the position 175 | of each pitch pulse during voiced speech. After much experiment 176 | I found that using just this frame's Wo improved quality for UV 177 | sounds compared to interpolating two frames Wo like this: 178 | 179 | ex_phase[0] += (*prev_Wo+model->Wo)*N_SAMP/2; 180 | */ 181 | 182 | ex_phase[0] += (model->Wo)*n_samp; 183 | ex_phase[0] -= TWO_PI*floorf(ex_phase[0]/TWO_PI + 0.5); 184 | 185 | for(m=1; m<=model->L; m++) { 186 | 187 | /* generate excitation */ 188 | 189 | if (model->voiced) { 190 | 191 | Ex[m].real = cosf(ex_phase[0]*m); 192 | Ex[m].imag = sinf(ex_phase[0]*m); 193 | } 194 | else { 195 | 196 | /* When a few samples were tested I found that LPC filter 197 | phase is not needed in the unvoiced case, but no harm in 198 | keeping it. 199 | */ 200 | float phi = TWO_PI*(float)codec2_rand()/CODEC2_RAND_MAX; 201 | Ex[m].real = cosf(phi); 202 | Ex[m].imag = sinf(phi); 203 | } 204 | 205 | /* filter using LPC filter */ 206 | 207 | A_[m].real = H[m].real*Ex[m].real - H[m].imag*Ex[m].imag; 208 | A_[m].imag = H[m].imag*Ex[m].real + H[m].real*Ex[m].imag; 209 | 210 | /* modify sinusoidal phase */ 211 | 212 | new_phi = atan2f(A_[m].imag, A_[m].real+1E-12); 213 | model->phi[m] = new_phi; 214 | } 215 | 216 | } 217 | 218 | 219 | /*---------------------------------------------------------------------------*\ 220 | 221 | FUNCTION....: mag_to_phase 222 | AUTHOR......: David Rowe 223 | DATE CREATED: Jan 2017 224 | 225 | Algorithm for http://www.dsprelated.com/showcode/20.php ported to C. See 226 | also Octave function mag_to_phase.m 227 | 228 | Given a magnitude spectrum in dB, returns a minimum-phase phase 229 | spectra. 230 | 231 | \*---------------------------------------------------------------------------*/ 232 | 233 | void mag_to_phase(float phase[], /* Nfft/2+1 output phase samples in radians */ 234 | float Gdbfk[], /* Nfft/2+1 postive freq amplitudes samples in dB */ 235 | int Nfft, 236 | codec2_fft_cfg fft_fwd_cfg, 237 | codec2_fft_cfg fft_inv_cfg 238 | ) 239 | { 240 | COMP Sdb[Nfft], c[Nfft], cf[Nfft], Cf[Nfft]; 241 | int Ns = Nfft/2+1; 242 | int i; 243 | 244 | /* install negative frequency components, 1/Nfft takes into 245 | account kiss fft lack of scaling on ifft */ 246 | 247 | Sdb[0].real = Gdbfk[0]; 248 | Sdb[0].imag = 0.0; 249 | for(i=1; i. 26 | */ 27 | 28 | #ifndef __PHASE__ 29 | #define __PHASE__ 30 | 31 | #include "codec2_fft.h" 32 | #include "comp.h" 33 | 34 | void sample_phase(MODEL *model, COMP filter_phase[], COMP A[]); 35 | void phase_synth_zero_order(int n_samp, MODEL *model, float *ex_phase, COMP filter_phase[]); 36 | 37 | void mag_to_phase(float phase[], float Gdbfk[], int Nfft, codec2_fft_cfg fwd_cfg, codec2_fft_cfg inv_cfg); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /postfilter.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: postfilter.c 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 13/09/09 6 | 7 | Postfilter to improve sound quality for speech with high levels of 8 | background noise. Unlike mixed-excitation models requires no bits 9 | to be transmitted to handle background noise. 10 | 11 | \*---------------------------------------------------------------------------*/ 12 | 13 | /* 14 | Copyright (C) 2009 David Rowe 15 | 16 | All rights reserved. 17 | 18 | This program is free software; you can redistribute it and/or modify 19 | it under the terms of the GNU Lesser General Public License version 2.1, as 20 | published by the Free Software Foundation. This program is 21 | distributed in the hope that it will be useful, but WITHOUT ANY 22 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 24 | License for more details. 25 | 26 | You should have received a copy of the GNU Lesser General Public License 27 | along with this program; if not, see . 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "defines.h" 36 | #include "comp.h" 37 | #include "dump.h" 38 | #include "sine.h" 39 | #include "postfilter.h" 40 | 41 | /*---------------------------------------------------------------------------*\ 42 | 43 | DEFINES 44 | 45 | \*---------------------------------------------------------------------------*/ 46 | 47 | #define BG_THRESH 40.0 /* only consider low levels signals for bg_est */ 48 | #define BG_BETA 0.1 /* averaging filter constant */ 49 | #define BG_MARGIN 6.0 /* harmonics this far above BG noise are 50 | randomised. Helped make bg noise less 51 | spikey (impulsive) for mmt1, but speech was 52 | perhaps a little rougher. 53 | */ 54 | 55 | /*---------------------------------------------------------------------------*\ 56 | 57 | postfilter() 58 | 59 | The post filter is designed to help with speech corrupted by 60 | background noise. The zero phase model tends to make speech with 61 | background noise sound "clicky". With high levels of background 62 | noise the low level inter-formant parts of the spectrum will contain 63 | noise rather than speech harmonics, so modelling them as voiced 64 | (i.e. a continuous, non-random phase track) is inaccurate. 65 | 66 | Some codecs (like MBE) have a mixed voicing model that breaks the 67 | spectrum into voiced and unvoiced regions. Several bits/frame 68 | (5-12) are required to transmit the frequency selective voicing 69 | information. Mixed excitation also requires accurate voicing 70 | estimation (parameter estimators always break occasionally under 71 | exceptional conditions). 72 | 73 | In our case we use a post filter approach which requires no 74 | additional bits to be transmitted. The decoder measures the average 75 | level of the background noise during unvoiced frames. If a harmonic 76 | is less than this level it is made unvoiced by randomising it's 77 | phases. 78 | 79 | This idea is rather experimental. Some potential problems that may 80 | happen: 81 | 82 | 1/ If someone says "aaaaaaaahhhhhhhhh" will background estimator track 83 | up to speech level? This would be a bad thing. 84 | 85 | 2/ If background noise suddenly dissapears from the source speech does 86 | estimate drop quickly? What is noise suddenly re-appears? 87 | 88 | 3/ Background noise with a non-flat sepctrum. Current algorithm just 89 | comsiders scpetrum as a whole, but this could be broken up into 90 | bands, each with their own estimator. 91 | 92 | 4/ Males and females with the same level of background noise. Check 93 | performance the same. Changing Wo affects width of each band, may 94 | affect bg energy estimates. 95 | 96 | 5/ Not sure what happens during long periods of voiced speech 97 | e.g. "sshhhhhhh" 98 | 99 | \*---------------------------------------------------------------------------*/ 100 | 101 | void postfilter( 102 | MODEL *model, 103 | float *bg_est 104 | ) 105 | { 106 | int m, uv; 107 | float e, thresh; 108 | 109 | /* determine average energy across spectrum */ 110 | 111 | e = 1E-12; 112 | for(m=1; m<=model->L; m++) 113 | e += model->A[m]*model->A[m]; 114 | 115 | assert(e > 0.0); 116 | e = 10.0*log10f(e/model->L); 117 | 118 | /* If beneath threhold, update bg estimate. The idea 119 | of the threshold is to prevent updating during high level 120 | speech. */ 121 | 122 | if ((e < BG_THRESH) && !model->voiced) 123 | *bg_est = *bg_est*(1.0 - BG_BETA) + e*BG_BETA; 124 | 125 | /* now mess with phases during voiced frames to make any harmonics 126 | less then our background estimate unvoiced. 127 | */ 128 | 129 | uv = 0; 130 | thresh = powf(10.0, (*bg_est + BG_MARGIN)/20.0); 131 | if (model->voiced) 132 | for(m=1; m<=model->L; m++) 133 | if (model->A[m] < thresh) { 134 | model->phi[m] = TWO_PI*(float)codec2_rand()/CODEC2_RAND_MAX; 135 | uv++; 136 | } 137 | 138 | #ifdef DUMP 139 | dump_bg(e, *bg_est, 100.0*uv/model->L); 140 | #endif 141 | 142 | } 143 | -------------------------------------------------------------------------------- /postfilter.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: postfilter.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 13/09/09 6 | 7 | Postfilter header file. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2009 David Rowe 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | #ifndef __POSTFILTER__ 29 | #define __POSTFILTER__ 30 | 31 | void postfilter(MODEL *model, float *bg_est); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /quantise.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: quantise.h 4 | AUTHOR......: David Rowe 5 | DATE CREATED: 31/5/92 6 | 7 | Quantisation functions for the sinusoidal coder. 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | All rights reserved. 13 | 14 | This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU Lesser General Public License version 2.1, as 16 | published by the Free Software Foundation. This program is 17 | distributed in the hope that it will be useful, but WITHOUT ANY 18 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 20 | License for more details. 21 | 22 | You should have received a copy of the GNU Lesser General Public License 23 | along with this program; if not, see . 24 | */ 25 | 26 | #ifndef __QUANTISE__ 27 | #define __QUANTISE__ 28 | 29 | #include "codec2_fft.h" 30 | #include "comp.h" 31 | 32 | #define WO_BITS 7 33 | #define WO_LEVELS (1<. 26 | */ 27 | 28 | #ifndef __SINE__ 29 | #define __SINE__ 30 | 31 | #include "defines.h" 32 | #include "comp.h" 33 | #include "codec2_fft.h" 34 | 35 | C2CONST c2const_create(int Fs); 36 | 37 | void make_analysis_window(C2CONST *c2const, codec2_fft_cfg fft_fwd_cfg, float w[], COMP W[]); 38 | float hpf(float x, float states[]); 39 | void dft_speech(C2CONST *c2const, codec2_fft_cfg fft_fwd_cfg, COMP Sw[], float Sn[], float w[]); 40 | void two_stage_pitch_refinement(C2CONST *c2const, MODEL *model, COMP Sw[]); 41 | void estimate_amplitudes(MODEL *model, COMP Sw[], COMP W[], int est_phase); 42 | float est_voicing_mbe(C2CONST *c2const, MODEL *model, COMP Sw[], COMP W[]); 43 | void make_synthesis_window(C2CONST *c2const, float Pn[]); 44 | void synthesise(int n_samp, codec2_fftr_cfg fftr_inv_cfg, float Sn_[], MODEL *model, float Pn[], int shift); 45 | 46 | #define CODEC2_RAND_MAX 32767 47 | int codec2_rand(void); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /test_bits_ofdm.h: -------------------------------------------------------------------------------- 1 | /* Generated by test_bits_ofdm_file() Octave function */ 2 | 3 | const int test_bits_ofdm[]={ 4 | 1, 5 | 1, 6 | 0, 7 | 1, 8 | 1, 9 | 0, 10 | 1, 11 | 0, 12 | 0, 13 | 1, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 0, 19 | 0, 20 | 0, 21 | 0, 22 | 0, 23 | 0, 24 | 0, 25 | 1, 26 | 0, 27 | 1, 28 | 1, 29 | 0, 30 | 0, 31 | 1, 32 | 0, 33 | 1, 34 | 0, 35 | 1, 36 | 0, 37 | 0, 38 | 0, 39 | 0, 40 | 0, 41 | 0, 42 | 0, 43 | 0, 44 | 0, 45 | 0, 46 | 1, 47 | 0, 48 | 0, 49 | 1, 50 | 1, 51 | 0, 52 | 0, 53 | 1, 54 | 1, 55 | 1, 56 | 1, 57 | 0, 58 | 0, 59 | 0, 60 | 0, 61 | 1, 62 | 1, 63 | 1, 64 | 0, 65 | 0, 66 | 1, 67 | 1, 68 | 0, 69 | 0, 70 | 1, 71 | 1, 72 | 1, 73 | 1, 74 | 1, 75 | 0, 76 | 0, 77 | 0, 78 | 0, 79 | 1, 80 | 0, 81 | 0, 82 | 1, 83 | 1, 84 | 0, 85 | 1, 86 | 0, 87 | 1, 88 | 1, 89 | 0, 90 | 1, 91 | 0, 92 | 1, 93 | 0, 94 | 0, 95 | 0, 96 | 0, 97 | 0, 98 | 0, 99 | 1, 100 | 0, 101 | 0, 102 | 1, 103 | 1, 104 | 0, 105 | 0, 106 | 0, 107 | 0, 108 | 1, 109 | 1, 110 | 0, 111 | 0, 112 | 0, 113 | 0, 114 | 0, 115 | 0, 116 | 1, 117 | 1, 118 | 0, 119 | 0, 120 | 1, 121 | 1, 122 | 1, 123 | 1, 124 | 0, 125 | 1, 126 | 0, 127 | 1, 128 | 0, 129 | 0, 130 | 0, 131 | 1, 132 | 1, 133 | 1, 134 | 1, 135 | 0, 136 | 0, 137 | 0, 138 | 1, 139 | 0, 140 | 0, 141 | 0, 142 | 0, 143 | 0, 144 | 1, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 1, 151 | 0, 152 | 0, 153 | 1, 154 | 0, 155 | 1, 156 | 0, 157 | 0, 158 | 1, 159 | 1, 160 | 1, 161 | 0, 162 | 0, 163 | 1, 164 | 1, 165 | 1, 166 | 0, 167 | 1, 168 | 1, 169 | 1, 170 | 1, 171 | 0, 172 | 0, 173 | 1, 174 | 0, 175 | 0, 176 | 1, 177 | 0, 178 | 0, 179 | 1, 180 | 1, 181 | 1, 182 | 0, 183 | 0, 184 | 0, 185 | 0, 186 | 1, 187 | 0, 188 | 0, 189 | 1, 190 | 0, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | 1, 199 | 0, 200 | 0, 201 | 0, 202 | 0, 203 | 0, 204 | 1, 205 | 0, 206 | 0, 207 | 0, 208 | 1, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 1, 216 | 1, 217 | 0, 218 | 0, 219 | 1, 220 | 1, 221 | 1, 222 | 1, 223 | 0, 224 | 1, 225 | 0, 226 | 1, 227 | 1, 228 | 1, 229 | 0, 230 | 1, 231 | 1, 232 | 1, 233 | 0, 234 | 0, 235 | 0, 236 | 0, 237 | 1, 238 | 0, 239 | 0, 240 | 0, 241 | 0 242 | }; 243 | 244 | const int payload_data_bits[]={ 245 | 1, 246 | 1, 247 | 0, 248 | 0, 249 | 1, 250 | 1, 251 | 1, 252 | 0, 253 | 1, 254 | 0, 255 | 1, 256 | 0, 257 | 0, 258 | 0, 259 | 0, 260 | 0, 261 | 0, 262 | 0, 263 | 0, 264 | 1, 265 | 1, 266 | 0, 267 | 1, 268 | 0, 269 | 1, 270 | 0, 271 | 0, 272 | 0, 273 | 0, 274 | 0, 275 | 0, 276 | 0, 277 | 0, 278 | 0, 279 | 0, 280 | 1, 281 | 0, 282 | 0, 283 | 0, 284 | 0, 285 | 0, 286 | 1, 287 | 1, 288 | 1, 289 | 1, 290 | 1, 291 | 1, 292 | 0, 293 | 1, 294 | 0, 295 | 1, 296 | 0, 297 | 1, 298 | 1, 299 | 0, 300 | 1, 301 | 0, 302 | 0, 303 | 0, 304 | 0, 305 | 1, 306 | 0, 307 | 1, 308 | 0, 309 | 1, 310 | 0, 311 | 1, 312 | 1, 313 | 1, 314 | 0, 315 | 1, 316 | 0, 317 | 1, 318 | 0, 319 | 1, 320 | 1, 321 | 0, 322 | 1, 323 | 1, 324 | 0, 325 | 1, 326 | 0, 327 | 0, 328 | 1, 329 | 0, 330 | 1, 331 | 0, 332 | 0, 333 | 0, 334 | 1, 335 | 1, 336 | 1, 337 | 0, 338 | 0, 339 | 0, 340 | 0, 341 | 0, 342 | 0, 343 | 0, 344 | 0, 345 | 1, 346 | 0, 347 | 0, 348 | 1, 349 | 1, 350 | 1, 351 | 0, 352 | 0, 353 | 1, 354 | 1, 355 | 1, 356 | 0 357 | }; 358 | 359 | const int test_codeword[]={ 360 | 1, 361 | 1, 362 | 0, 363 | 0, 364 | 1, 365 | 1, 366 | 1, 367 | 0, 368 | 1, 369 | 0, 370 | 1, 371 | 0, 372 | 0, 373 | 0, 374 | 0, 375 | 0, 376 | 0, 377 | 0, 378 | 0, 379 | 1, 380 | 1, 381 | 0, 382 | 1, 383 | 0, 384 | 1, 385 | 0, 386 | 0, 387 | 0, 388 | 0, 389 | 0, 390 | 0, 391 | 0, 392 | 0, 393 | 0, 394 | 0, 395 | 1, 396 | 0, 397 | 0, 398 | 0, 399 | 0, 400 | 0, 401 | 1, 402 | 1, 403 | 1, 404 | 1, 405 | 1, 406 | 1, 407 | 0, 408 | 1, 409 | 0, 410 | 1, 411 | 0, 412 | 1, 413 | 1, 414 | 0, 415 | 1, 416 | 0, 417 | 0, 418 | 0, 419 | 0, 420 | 1, 421 | 0, 422 | 1, 423 | 0, 424 | 1, 425 | 0, 426 | 1, 427 | 1, 428 | 1, 429 | 0, 430 | 1, 431 | 0, 432 | 1, 433 | 0, 434 | 1, 435 | 1, 436 | 0, 437 | 1, 438 | 1, 439 | 0, 440 | 1, 441 | 0, 442 | 0, 443 | 1, 444 | 0, 445 | 1, 446 | 0, 447 | 0, 448 | 0, 449 | 1, 450 | 1, 451 | 1, 452 | 0, 453 | 0, 454 | 0, 455 | 0, 456 | 0, 457 | 0, 458 | 0, 459 | 0, 460 | 1, 461 | 0, 462 | 0, 463 | 1, 464 | 1, 465 | 1, 466 | 0, 467 | 0, 468 | 1, 469 | 1, 470 | 1, 471 | 0, 472 | 0, 473 | 1, 474 | 0, 475 | 0, 476 | 1, 477 | 0, 478 | 0, 479 | 0, 480 | 0, 481 | 1, 482 | 1, 483 | 1, 484 | 0, 485 | 0, 486 | 1, 487 | 0, 488 | 0, 489 | 0, 490 | 1, 491 | 1, 492 | 0, 493 | 0, 494 | 1, 495 | 1, 496 | 0, 497 | 1, 498 | 1, 499 | 1, 500 | 0, 501 | 1, 502 | 0, 503 | 1, 504 | 1, 505 | 1, 506 | 1, 507 | 1, 508 | 0, 509 | 1, 510 | 0, 511 | 0, 512 | 0, 513 | 1, 514 | 0, 515 | 0, 516 | 0, 517 | 0, 518 | 0, 519 | 1, 520 | 0, 521 | 0, 522 | 1, 523 | 0, 524 | 0, 525 | 0, 526 | 0, 527 | 1, 528 | 1, 529 | 1, 530 | 0, 531 | 0, 532 | 0, 533 | 1, 534 | 0, 535 | 0, 536 | 0, 537 | 0, 538 | 1, 539 | 1, 540 | 0, 541 | 0, 542 | 1, 543 | 1, 544 | 0, 545 | 1, 546 | 1, 547 | 0, 548 | 0, 549 | 0, 550 | 0, 551 | 1, 552 | 0, 553 | 0, 554 | 0, 555 | 1, 556 | 0, 557 | 1, 558 | 0, 559 | 0, 560 | 1, 561 | 1, 562 | 1, 563 | 0, 564 | 0, 565 | 1, 566 | 0, 567 | 1, 568 | 1, 569 | 0, 570 | 0, 571 | 0, 572 | 0, 573 | 1, 574 | 0, 575 | 0, 576 | 0, 577 | 0, 578 | 1, 579 | 0, 580 | 0, 581 | 1, 582 | 0, 583 | 0 584 | }; 585 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*\ 2 | 3 | FILE........: version.h 4 | AUTHOR......: Tomas Härdin 5 | DATE CREATED: 03 November 2017 6 | 7 | Codec 2 VERSION #defines 8 | 9 | \*---------------------------------------------------------------------------*/ 10 | 11 | /* 12 | Copyright (C) 2017 Tomas Härdin 13 | 14 | All rights reserved. 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU Lesser General Public License version 2.1, as 18 | published by the Free Software Foundation. This program is 19 | distributed in the hope that it will be useful, but WITHOUT ANY 20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 | License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program; if not, see . 26 | */ 27 | 28 | //this functions both as an include guard and your typical HAVE macro 29 | #ifndef CODEC2_HAVE_VERSION 30 | #define CODEC2_HAVE_VERSION 31 | 32 | #define CODEC2_VERSION_MAJOR @CODEC2_VERSION_MAJOR@ 33 | #define CODEC2_VERSION_MINOR @CODEC2_VERSION_MINOR@ 34 | //#cmakedefine CODEC2_VERSION_PATCH @CODEC2_VERSION_PATCH@ 35 | #define CODEC2_VERSION "@CODEC2_VERSION@" 36 | 37 | #endif //CODEC2_HAVE_VERSION 38 | --------------------------------------------------------------------------------