mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			228 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
		
		
			
		
	
	
			228 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
| 
											12 years ago
										 | /* Copyright (C) 2006 Jean-Marc Valin */ | ||
|  | /**
 | ||
|  |    @file filterbank.c | ||
|  |    @brief Converting between psd and filterbank | ||
|  |  */ | ||
|  | /*
 | ||
|  |    Redistribution and use in source and binary forms, with or without | ||
|  |    modification, are permitted provided that the following conditions are | ||
|  |    met: | ||
|  | 
 | ||
|  |    1. Redistributions of source code must retain the above copyright notice, | ||
|  |    this list of conditions and the following disclaimer. | ||
|  | 
 | ||
|  |    2. 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. | ||
|  | 
 | ||
|  |    3. The name of the author may not be used to endorse or promote products | ||
|  |    derived from this software without specific prior written permission. | ||
|  | 
 | ||
|  |    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. | ||
|  | */ | ||
|  | 
 | ||
|  | #ifdef HAVE_CONFIG_H
 | ||
|  | #include "config.h"
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #include "filterbank.h"
 | ||
|  | #include "arch.h"
 | ||
|  | #include <math.h>
 | ||
|  | #include "math_approx.h"
 | ||
|  | #include "os_support.h"
 | ||
|  |        | ||
|  | #ifdef FIXED_POINT
 | ||
|  | 
 | ||
|  | #define toBARK(n)   (MULT16_16(26829,spx_atan(SHR32(MULT16_16(97,n),2))) + MULT16_16(4588,spx_atan(MULT16_32_Q15(20,MULT16_16(n,n)))) + MULT16_16(3355,n))
 | ||
|  |        | ||
|  | #else
 | ||
|  | #define toBARK(n)   (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n))
 | ||
|  | #endif
 | ||
|  |         | ||
|  | #define toMEL(n)    (2595.f*log10(1.f+(n)/700.f))
 | ||
|  | 
 | ||
|  | FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type) | ||
|  | { | ||
|  |    FilterBank *bank; | ||
|  |    spx_word32_t df; | ||
|  |    spx_word32_t max_mel, mel_interval; | ||
|  |    int i; | ||
|  |    int id1; | ||
|  |    int id2; | ||
|  |    df = DIV32(SHL32(sampling,15),MULT16_16(2,len)); | ||
|  |    max_mel = toBARK(EXTRACT16(sampling/2)); | ||
|  |    mel_interval = PDIV32(max_mel,banks-1); | ||
|  |     | ||
|  |    bank = (FilterBank*)speex_alloc(sizeof(FilterBank)); | ||
|  |    bank->nb_banks = banks; | ||
|  |    bank->len = len; | ||
|  |    bank->bank_left = (int*)speex_alloc(len*sizeof(int)); | ||
|  |    bank->bank_right = (int*)speex_alloc(len*sizeof(int)); | ||
|  |    bank->filter_left = (spx_word16_t*)speex_alloc(len*sizeof(spx_word16_t)); | ||
|  |    bank->filter_right = (spx_word16_t*)speex_alloc(len*sizeof(spx_word16_t)); | ||
|  |    /* Think I can safely disable normalisation that for fixed-point (and probably float as well) */ | ||
|  | #ifndef FIXED_POINT
 | ||
|  |    bank->scaling = (float*)speex_alloc(banks*sizeof(float)); | ||
|  | #endif
 | ||
|  |    for (i=0;i<len;i++) | ||
|  |    { | ||
|  |       spx_word16_t curr_freq; | ||
|  |       spx_word32_t mel; | ||
|  |       spx_word16_t val; | ||
|  |       curr_freq = EXTRACT16(MULT16_32_P15(i,df)); | ||
|  |       mel = toBARK(curr_freq); | ||
|  |       if (mel > max_mel) | ||
|  |          break; | ||
|  | #ifdef FIXED_POINT
 | ||
|  |       id1 = DIV32(mel,mel_interval); | ||
|  | #else      
 | ||
|  |       id1 = (int)(floor(mel/mel_interval)); | ||
|  | #endif
 | ||
|  |       if (id1>banks-2) | ||
|  |       { | ||
|  |          id1 = banks-2; | ||
|  |          val = Q15_ONE; | ||
|  |       } else { | ||
|  |          val = DIV32_16(mel - id1*mel_interval,EXTRACT16(PSHR32(mel_interval,15))); | ||
|  |       } | ||
|  |       id2 = id1+1; | ||
|  |       bank->bank_left[i] = id1; | ||
|  |       bank->filter_left[i] = SUB16(Q15_ONE,val); | ||
|  |       bank->bank_right[i] = id2; | ||
|  |       bank->filter_right[i] = val; | ||
|  |    } | ||
|  |     | ||
|  |    /* Think I can safely disable normalisation for fixed-point (and probably float as well) */ | ||
|  | #ifndef FIXED_POINT
 | ||
|  |    for (i=0;i<bank->nb_banks;i++) | ||
|  |       bank->scaling[i] = 0; | ||
|  |    for (i=0;i<bank->len;i++) | ||
|  |    { | ||
|  |       int id = bank->bank_left[i]; | ||
|  |       bank->scaling[id] += bank->filter_left[i]; | ||
|  |       id = bank->bank_right[i]; | ||
|  |       bank->scaling[id] += bank->filter_right[i]; | ||
|  |    } | ||
|  |    for (i=0;i<bank->nb_banks;i++) | ||
|  |       bank->scaling[i] = Q15_ONE/(bank->scaling[i]); | ||
|  | #endif
 | ||
|  |    return bank; | ||
|  | } | ||
|  | 
 | ||
|  | void filterbank_destroy(FilterBank *bank) | ||
|  | { | ||
|  |    speex_free(bank->bank_left); | ||
|  |    speex_free(bank->bank_right); | ||
|  |    speex_free(bank->filter_left); | ||
|  |    speex_free(bank->filter_right); | ||
|  | #ifndef FIXED_POINT
 | ||
|  |    speex_free(bank->scaling); | ||
|  | #endif
 | ||
|  |    speex_free(bank); | ||
|  | } | ||
|  | 
 | ||
|  | void filterbank_compute_bank32(FilterBank *bank, spx_word32_t *ps, spx_word32_t *mel) | ||
|  | { | ||
|  |    int i; | ||
|  |    for (i=0;i<bank->nb_banks;i++) | ||
|  |       mel[i] = 0; | ||
|  | 
 | ||
|  |    for (i=0;i<bank->len;i++) | ||
|  |    { | ||
|  |       int id; | ||
|  |       id = bank->bank_left[i]; | ||
|  |       mel[id] += MULT16_32_P15(bank->filter_left[i],ps[i]); | ||
|  |       id = bank->bank_right[i]; | ||
|  |       mel[id] += MULT16_32_P15(bank->filter_right[i],ps[i]); | ||
|  |    } | ||
|  |    /* Think I can safely disable normalisation that for fixed-point (and probably float as well) */ | ||
|  | #ifndef FIXED_POINT
 | ||
|  |    /*for (i=0;i<bank->nb_banks;i++)
 | ||
|  |       mel[i] = MULT16_32_P15(Q15(bank->scaling[i]),mel[i]); | ||
|  |    */ | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | void filterbank_compute_psd16(FilterBank *bank, spx_word16_t *mel, spx_word16_t *ps) | ||
|  | { | ||
|  |    int i; | ||
|  |    for (i=0;i<bank->len;i++) | ||
|  |    { | ||
|  |       spx_word32_t tmp; | ||
|  |       int id1, id2; | ||
|  |       id1 = bank->bank_left[i]; | ||
|  |       id2 = bank->bank_right[i]; | ||
|  |       tmp = MULT16_16(mel[id1],bank->filter_left[i]); | ||
|  |       tmp += MULT16_16(mel[id2],bank->filter_right[i]); | ||
|  |       ps[i] = EXTRACT16(PSHR32(tmp,15)); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifndef FIXED_POINT
 | ||
|  | void filterbank_compute_bank(FilterBank *bank, float *ps, float *mel) | ||
|  | { | ||
|  |    int i; | ||
|  |    for (i=0;i<bank->nb_banks;i++) | ||
|  |       mel[i] = 0; | ||
|  | 
 | ||
|  |    for (i=0;i<bank->len;i++) | ||
|  |    { | ||
|  |       int id = bank->bank_left[i]; | ||
|  |       mel[id] += bank->filter_left[i]*ps[i]; | ||
|  |       id = bank->bank_right[i]; | ||
|  |       mel[id] += bank->filter_right[i]*ps[i]; | ||
|  |    } | ||
|  |    for (i=0;i<bank->nb_banks;i++) | ||
|  |       mel[i] *= bank->scaling[i]; | ||
|  | } | ||
|  | 
 | ||
|  | void filterbank_compute_psd(FilterBank *bank, float *mel, float *ps) | ||
|  | { | ||
|  |    int i; | ||
|  |    for (i=0;i<bank->len;i++) | ||
|  |    { | ||
|  |       int id = bank->bank_left[i]; | ||
|  |       ps[i] = mel[id]*bank->filter_left[i]; | ||
|  |       id = bank->bank_right[i]; | ||
|  |       ps[i] += mel[id]*bank->filter_right[i]; | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | void filterbank_psy_smooth(FilterBank *bank, float *ps, float *mask) | ||
|  | { | ||
|  |    /* Low freq slope: 14 dB/Bark*/ | ||
|  |    /* High freq slope: 9 dB/Bark*/ | ||
|  |    /* Noise vs tone: 5 dB difference */ | ||
|  |    /* FIXME: Temporary kludge */ | ||
|  |    float bark[100]; | ||
|  |    int i; | ||
|  |    /* Assumes 1/3 Bark resolution */ | ||
|  |    float decay_low = 0.34145f; | ||
|  |    float decay_high = 0.50119f; | ||
|  |    filterbank_compute_bank(bank, ps, bark); | ||
|  |    for (i=1;i<bank->nb_banks;i++) | ||
|  |    { | ||
|  |       /*float decay_high = 13-1.6*log10(bark[i-1]);
 | ||
|  |       decay_high = pow(10,(-decay_high/30.f));*/ | ||
|  |       bark[i] = bark[i] + decay_high*bark[i-1]; | ||
|  |    } | ||
|  |    for (i=bank->nb_banks-2;i>=0;i--) | ||
|  |    { | ||
|  |       bark[i] = bark[i] + decay_low*bark[i+1]; | ||
|  |    } | ||
|  |    filterbank_compute_psd(bank, bark, mask); | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 |