q3.28 changes
This commit is contained in:
		
							parent
							
								
									009dd2e698
								
							
						
					
					
						commit
						481219341d
					
				|  | @ -73,12 +73,12 @@ void bqf_lowpass_config(double fs, double f0, double Q, bqf_coeff_t *coefficient | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -123,12 +123,12 @@ void bqf_highpass_config(double fs, double f0, double Q, bqf_coeff_t *coefficien | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -168,12 +168,12 @@ void bqf_bandpass_skirt_config(double fs, double f0, double Q, bqf_coeff_t *coef | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -213,12 +213,12 @@ void bqf_bandpass_peak_config(double fs, double f0, double Q, bqf_coeff_t *coeff | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -257,12 +257,12 @@ void bqf_notch_config(double fs, double f0, double Q, bqf_coeff_t *coefficients) | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -300,12 +300,12 @@ void bqf_allpass_config(double fs, double f0, double Q, bqf_coeff_t *coefficient | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -353,12 +353,12 @@ void bqf_peaking_config(double fs, double f0, double dBgain, double Q, | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -406,12 +406,12 @@ void bqf_lowshelf_config(double fs, double f0, double dBgain, double Q, | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -459,16 +459,16 @@ void bqf_highshelf_config(double fs, double f0, double dBgain, double Q, | ||||||
|     a2 = a2 / a0; |     a2 = a2 / a0; | ||||||
|     a0 = 1.0; |     a0 = 1.0; | ||||||
| 
 | 
 | ||||||
|     coefficients->b0 = fix16_from_dbl(b0); |     coefficients->b0 = fix3_28_from_dbl(b0); | ||||||
|     coefficients->b1 = fix16_from_dbl(b1); |     coefficients->b1 = fix3_28_from_dbl(b1); | ||||||
|     coefficients->b2 = fix16_from_dbl(b2); |     coefficients->b2 = fix3_28_from_dbl(b2); | ||||||
|     coefficients->a0 = fix16_from_dbl(a0); |     coefficients->a0 = fix3_28_from_dbl(a0); | ||||||
|     coefficients->a1 = fix16_from_dbl(a1); |     coefficients->a1 = fix3_28_from_dbl(a1); | ||||||
|     coefficients->a2 = fix16_from_dbl(a2); |     coefficients->a2 = fix3_28_from_dbl(a2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fix16_t bqf_transform(fix16_t x, bqf_coeff_t *coefficients, bqf_mem_t *memory) { | fix3_28_t bqf_transform(fix3_28_t x, bqf_coeff_t *coefficients, bqf_mem_t *memory) { | ||||||
|     fix16_t y = fix16_mul(coefficients->b0, x) - |     fix3_28_t y = fix16_mul(coefficients->b0, x) - | ||||||
|             fix16_mul(coefficients->a1, memory->y_1) + |             fix16_mul(coefficients->a1, memory->y_1) + | ||||||
|             fix16_mul(coefficients->b1, memory->x_1) - |             fix16_mul(coefficients->b1, memory->x_1) - | ||||||
|             fix16_mul(coefficients->a2, memory->y_2) + |             fix16_mul(coefficients->a2, memory->y_2) + | ||||||
|  |  | ||||||
|  | @ -26,19 +26,19 @@ | ||||||
| #include "fix16.h" | #include "fix16.h" | ||||||
| 
 | 
 | ||||||
| typedef struct _bqf_coeff_t { | typedef struct _bqf_coeff_t { | ||||||
|     fix16_t a0; |     fix3_28_t a0; | ||||||
|     fix16_t a1; |     fix3_28_t a1; | ||||||
|     fix16_t a2; |     fix3_28_t a2; | ||||||
|     fix16_t b0; |     fix3_28_t b0; | ||||||
|     fix16_t b1; |     fix3_28_t b1; | ||||||
|     fix16_t b2; |     fix3_28_t b2; | ||||||
| } bqf_coeff_t; | } bqf_coeff_t; | ||||||
| 
 | 
 | ||||||
| typedef struct _bqf_mem_t { | typedef struct _bqf_mem_t { | ||||||
|     fix16_t x_1; |     fix3_28_t x_1; | ||||||
|     fix16_t x_2; |     fix3_28_t x_2; | ||||||
|     fix16_t y_1; |     fix3_28_t y_1; | ||||||
|     fix16_t y_2; |     fix3_28_t y_2; | ||||||
| } bqf_mem_t; | } bqf_mem_t; | ||||||
| 
 | 
 | ||||||
| // In reality we do not have enough CPU resource to run 8 filtering
 | // In reality we do not have enough CPU resource to run 8 filtering
 | ||||||
|  | @ -65,7 +65,7 @@ void bqf_peaking_config(double, double, double, double, bqf_coeff_t *); | ||||||
| void bqf_lowshelf_config(double, double, double, double, bqf_coeff_t *); | void bqf_lowshelf_config(double, double, double, double, bqf_coeff_t *); | ||||||
| void bqf_highshelf_config(double, double, double, double, bqf_coeff_t *); | void bqf_highshelf_config(double, double, double, double, bqf_coeff_t *); | ||||||
| 
 | 
 | ||||||
| fix16_t bqf_transform(fix16_t, bqf_coeff_t *, bqf_mem_t *); | fix3_28_t bqf_transform(fix3_28_t, bqf_coeff_t *, bqf_mem_t *); | ||||||
| void bqf_memreset(bqf_mem_t *); | void bqf_memreset(bqf_mem_t *); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -179,12 +179,12 @@ void apply_filter_configuration(filter_configuration_tlv *filters) { | ||||||
|                 uint32_t checksum = 0; |                 uint32_t checksum = 0; | ||||||
|                 for (int i = 0; i < sizeof(filter6) / 4; i++) checksum ^= ((uint32_t*) args)[i]; |                 for (int i = 0; i < sizeof(filter6) / 4; i++) checksum ^= ((uint32_t*) args)[i]; | ||||||
|                 if (checksum != bqf_filter_checksum[filter_stages]) { |                 if (checksum != bqf_filter_checksum[filter_stages]) { | ||||||
|                     bqf_filters_left[filter_stages].a0 = fix16_from_dbl(1.0); |                     bqf_filters_left[filter_stages].a0 = fix3_28_from_dbl(1.0); | ||||||
|                     bqf_filters_left[filter_stages].a1 = fix16_from_dbl(args->a1/args->a0); |                     bqf_filters_left[filter_stages].a1 = fix3_28_from_dbl(args->a1/args->a0); | ||||||
|                     bqf_filters_left[filter_stages].a2 = fix16_from_dbl(args->a2/args->a0); |                     bqf_filters_left[filter_stages].a2 = fix3_28_from_dbl(args->a2/args->a0); | ||||||
|                     bqf_filters_left[filter_stages].b0 = fix16_from_dbl(args->b0/args->a0); |                     bqf_filters_left[filter_stages].b0 = fix3_28_from_dbl(args->b0/args->a0); | ||||||
|                     bqf_filters_left[filter_stages].b1 = fix16_from_dbl(args->b1/args->a0); |                     bqf_filters_left[filter_stages].b1 = fix3_28_from_dbl(args->b1/args->a0); | ||||||
|                     bqf_filters_left[filter_stages].b2 = fix16_from_dbl(args->b2/args->a0); |                     bqf_filters_left[filter_stages].b2 = fix3_28_from_dbl(args->b2/args->a0); | ||||||
|                     memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t)); |                     memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t)); | ||||||
|                     bqf_filter_checksum[filter_stages] = checksum; |                     bqf_filter_checksum[filter_stages] = checksum; | ||||||
|                 } |                 } | ||||||
|  | @ -198,8 +198,8 @@ void apply_filter_configuration(filter_configuration_tlv *filters) { | ||||||
|         if (type_changed) { |         if (type_changed) { | ||||||
|             // The memory structure stores the last 2 input samples, we can replay them into
 |             // The memory structure stores the last 2 input samples, we can replay them into
 | ||||||
|             // the new filter rather than starting again from scratch.
 |             // the new filter rather than starting again from scratch.
 | ||||||
|             fix16_t left[2] = { bqf_filters_mem_left[filter_stages].x_2, bqf_filters_mem_left[filter_stages].x_1 }; |             fix3_28_t left[2] = { bqf_filters_mem_left[filter_stages].x_2, bqf_filters_mem_left[filter_stages].x_1 }; | ||||||
|             fix16_t right[2] = { bqf_filters_mem_right[filter_stages].x_2, bqf_filters_mem_right[filter_stages].x_1 }; |             fix3_28_t right[2] = { bqf_filters_mem_right[filter_stages].x_2, bqf_filters_mem_right[filter_stages].x_1 }; | ||||||
| 
 | 
 | ||||||
|             bqf_memreset(&bqf_filters_mem_left[filter_stages]); |             bqf_memreset(&bqf_filters_mem_left[filter_stages]); | ||||||
|             bqf_memreset(&bqf_filters_mem_right[filter_stages]); |             bqf_memreset(&bqf_filters_mem_right[filter_stages]); | ||||||
|  | @ -305,7 +305,7 @@ bool apply_configuration(tlv_header *config) { | ||||||
| #ifndef TEST_TARGET | #ifndef TEST_TARGET | ||||||
|             case PREPROCESSING_CONFIGURATION: { |             case PREPROCESSING_CONFIGURATION: { | ||||||
|                 preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv; |                 preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv; | ||||||
|                 preprocessing.preamp = fix16_from_dbl(1.0 + preprocessing_config->preamp); |                 preprocessing.preamp = fix3_28_from_dbl(1.0 + preprocessing_config->preamp); | ||||||
|                 preprocessing.reverse_stereo = preprocessing_config->reverse_stereo; |                 preprocessing.reverse_stereo = preprocessing_config->reverse_stereo; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  | @ -546,4 +546,4 @@ void apply_config_changes() { | ||||||
|         apply_configuration((tlv_header*) working_configuration[active_configuration]); |         apply_configuration((tlv_header*) working_configuration[active_configuration]); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -60,17 +60,36 @@ fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) { | ||||||
|     return inArg0 * inArg1; |     return inArg0 * inArg1; | ||||||
| } | } | ||||||
| #else | #else | ||||||
| fix16_t fix16_from_s16sample(int16_t a) { | 
 | ||||||
|     return a * fix16_lsb; | /// @brief Produces a fixed point number from a 16-bit signed integer, normalized to ]-1,1[.
 | ||||||
|  | /// @param a Signed 16-bit integer.
 | ||||||
|  | /// @return A fixed point number in Q3.28 format, with input normalized to ]-1,1[.
 | ||||||
|  | fix3_28_t norm_fix3_28_from_s16sample(int16_t a) { | ||||||
|  |     /* So, we're using a Q3.28 fixed point system here, and we want the incoming
 | ||||||
|  |        audio signal to be represented as a number between -1 and 1. To do this, | ||||||
|  |        we need the 16-bit value to map to the 28-bit right-of-decimal field in | ||||||
|  |        our fixed point number. 28-16 = 12, so we shift the incoming value by | ||||||
|  |        that much to covert it to the desired Q3.28 format and do the normalization | ||||||
|  |        all in one go. | ||||||
|  |     */ | ||||||
|  |     return (fix3_28_t)a << 12; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int16_t fix16_to_s16sample(fix16_t a) { | /// @brief Convert fixed point samples into signed integer. Used to convert
 | ||||||
|  | ///        calculated sample to one that the DAC can understand.
 | ||||||
|  | /// @param a
 | ||||||
|  | /// @return Signed 16-bit integer.
 | ||||||
|  | int16_t norm_fix3_28_to_s16sample(fix3_28_t a) { | ||||||
|     // Handle rounding up front, adding one can cause an overflow/underflow
 |     // Handle rounding up front, adding one can cause an overflow/underflow
 | ||||||
|  | 
 | ||||||
|  |     // It's not clear exactly how this works, so we'll disable it for now.
 | ||||||
|  |     /*
 | ||||||
|     if (a < 0) { |     if (a < 0) { | ||||||
|         a -= (fix16_lsb >> 1); |         a -= (fix16_lsb >> 1); | ||||||
|     } else { |     } else { | ||||||
|         a += (fix16_lsb >> 1); |         a += (fix16_lsb >> 1); | ||||||
|     } |     } | ||||||
|  |     */ | ||||||
| 
 | 
 | ||||||
|     // Saturate the value if an overflow has occurred
 |     // Saturate the value if an overflow has occurred
 | ||||||
|     uint32_t upper = (a >> 30); |     uint32_t upper = (a >> 30); | ||||||
|  | @ -85,25 +104,31 @@ int16_t fix16_to_s16sample(fix16_t a) { | ||||||
|             return SHRT_MAX; |             return SHRT_MAX; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return (a >> 15); |     /* When we converted the USB audio sample to a fixed point number, we applied
 | ||||||
|  |        a normalization, or a gain of 1/65536. To convert it back, we can undo that | ||||||
|  |        by shifting it back by the same amount we shifted it in the first place. */ | ||||||
|  |     return (a >> 12); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fix16_t fix16_from_dbl(double a) { | 
 | ||||||
|  | fix3_28_t fix3_28_from_dbl(double a) { | ||||||
|     double temp = a * fix16_one; |     double temp = a * fix16_one; | ||||||
|     temp += (double)((temp >= 0) ? 0.5f : -0.5f); |     temp += (double)((temp >= 0) ? 0.5f : -0.5f); | ||||||
|     return (fix16_t)temp; |     return (fix3_28_t)temp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| double fix16_to_dbl(fix16_t a) { | /// @brief Multiplies two fixed point numbers in Q3.28 format together.
 | ||||||
|     return (double)a / fix16_one; | /// @param inArg0 Q3.28 format fixed point number.
 | ||||||
| } | /// @param inArg1 Q3.28 format fixed point number.
 | ||||||
| 
 | /// @return A Q3.28 fixed point number that represents the truncated result of inArg0 x inArg1.
 | ||||||
| // We work in 64bits then shift the result to get
 | fix3_28_t fix16_mul(fix3_28_t inArg0, fix3_28_t inArg1) { | ||||||
| // the bit representing 1 back into the correct position.
 |  | ||||||
| // i.e. 1*1 == 1, so 20000000^2 >> 25 = 20000000
 |  | ||||||
| fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) { |  | ||||||
|     const int64_t product = (int64_t)inArg0 * inArg1; |     const int64_t product = (int64_t)inArg0 * inArg1; | ||||||
|     fix16_t result = product >> 25; | 
 | ||||||
|  |     /* Since we're expecting 2 Q3.28 numbers, the multiplication result should be a Q7.56 number.
 | ||||||
|  |        To bring this number back to the right order of magnitude, we need to shift | ||||||
|  |        it to the right by 28. */ | ||||||
|  |     fix3_28_t result = product >> 28; | ||||||
|  | 
 | ||||||
|     // Handle rounding where we are choppping off low order bits
 |     // Handle rounding where we are choppping off low order bits
 | ||||||
|     // Disabled for now, too much load. We get crackling when adjusting
 |     // Disabled for now, too much load. We get crackling when adjusting
 | ||||||
|     // the volume.
 |     // the volume.
 | ||||||
|  |  | ||||||
|  | @ -32,24 +32,29 @@ typedef double fix16_t; | ||||||
| static const fix16_t fix16_zero = 0; | static const fix16_t fix16_zero = 0; | ||||||
| static const fix16_t fix16_one = 1; | static const fix16_t fix16_one = 1; | ||||||
| #else | #else | ||||||
| // We normalize all values into the range -32..32 with 1 extra bit for overflows
 | 
 | ||||||
| // and one bit for the sign. We allow fixed point values to overflow, but they
 | /// @brief Fixed point math type, in format Q3.28. One sign bit, 3 bits for left-of-decimal
 | ||||||
| // are clipped at the point they are written back to a s16sample.
 | ///and 28 for right-of-decimal. This arrangment works because we normalize the incoming USB
 | ||||||
| //
 | ///audio data to ]-1,1[ before operating on it, to push as much of the precision in the signal
 | ||||||
| // The reason for normalizing the samples is because the filter coefficients are
 | ///to the right of the decimal as possible.
 | ||||||
| // small (usually well within in the range -32..32), by normalizing everything the coefficients
 | typedef int32_t fix3_28_t; | ||||||
| // get lots of additional bits of precision.
 | 
 | ||||||
| typedef int32_t fix16_t; | /// @brief Represents the number 1 in Q3.28. There are 3 bits and a sign bit to the left of the
 | ||||||
| static const fix16_t fix16_lsb = 0x8000; | ///decimal, so 1.0000 would be represented as 0b 0001 followed by 28 zeros.
 | ||||||
| static const fix16_t fix16_one = 0x002000000; | static const fix3_28_t fix16_one =    0x10000000; | ||||||
| static const fix16_t fix16_zero = 0x00000000; | 
 | ||||||
|  | /// @brief Represents zero in fixed point world.
 | ||||||
|  | static const fix3_28_t fix16_zero = 0x00000000; | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| fix16_t fix16_from_s16sample(int16_t); |  | ||||||
| int16_t fix16_to_s16sample(fix16_t); |  | ||||||
| fix16_t fix16_from_dbl(double); |  | ||||||
| double fix16_to_dbl(fix16_t); |  | ||||||
| 
 | 
 | ||||||
| fix16_t fix16_mul(fix16_t, fix16_t); | fix3_28_t norm_fix3_28_from_s16sample(int16_t); | ||||||
|  | 
 | ||||||
|  | int16_t norm_fix3_28_to_s16sample(fix3_28_t); | ||||||
|  | 
 | ||||||
|  | fix3_28_t fix3_28_from_dbl(double); | ||||||
|  | 
 | ||||||
|  | fix3_28_t fix16_mul(fix3_28_t, fix3_28_t); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | @ -143,12 +143,12 @@ static void _as_audio_packet(struct usb_endpoint *ep) { | ||||||
|     for (int j = 0; j < filter_stages; j++) { |     for (int j = 0; j < filter_stages; j++) { | ||||||
|         // Left channel filter
 |         // Left channel filter
 | ||||||
|         for (int i = 0; i < samples; i += 2) { |         for (int i = 0; i < samples; i += 2) { | ||||||
|             fix16_t x_f16 = fix16_mul(fix16_from_s16sample((int16_t) out[i]), preprocessing.preamp); |             fix3_28_t x_f16 = fix16_mul(norm_fix3_28_from_s16sample((int16_t) out[i]), preprocessing.preamp); | ||||||
| 
 | 
 | ||||||
|             x_f16 = bqf_transform(x_f16, &bqf_filters_left[j], |             x_f16 = bqf_transform(x_f16, &bqf_filters_left[j], | ||||||
|                 &bqf_filters_mem_left[j]); |                 &bqf_filters_mem_left[j]); | ||||||
| 
 | 
 | ||||||
|             out[i] = (int32_t) fix16_to_s16sample(x_f16); |             out[i] = (int32_t) norm_fix3_28_to_s16sample(x_f16); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -189,12 +189,12 @@ void core1_entry() { | ||||||
| 
 | 
 | ||||||
|         for (int j = 0; j < filter_stages; j++) { |         for (int j = 0; j < filter_stages; j++) { | ||||||
|             for (int i = 1; i < samples; i += 2) { |             for (int i = 1; i < samples; i += 2) { | ||||||
|                 fix16_t x_f16 = fix16_mul(fix16_from_s16sample((int16_t) out[i]), preprocessing.preamp); |                 fix3_28_t x_f16 = fix16_mul(norm_fix3_28_from_s16sample((int16_t) out[i]), preprocessing.preamp); | ||||||
| 
 | 
 | ||||||
|                 x_f16 = bqf_transform(x_f16, &bqf_filters_right[j], |                 x_f16 = bqf_transform(x_f16, &bqf_filters_right[j], | ||||||
|                     &bqf_filters_mem_right[j]); |                     &bqf_filters_mem_right[j]); | ||||||
| 
 | 
 | ||||||
|                 out[i] = (int16_t) fix16_to_s16sample(x_f16); |                 out[i] = (int16_t) norm_fix3_28_to_s16sample(x_f16); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -773,8 +773,8 @@ static bool do_set_current(struct usb_setup_packet *setup) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void _tf_send_control_in_ack(__unused struct usb_endpoint *endpoint, __unused struct usb_transfer *transfer) { | static void _tf_send_control_in_ack(__unused struct usb_endpoint *endpoint, __unused struct usb_transfer *transfer) { | ||||||
|     assert(endpoint == &usb_control_in); |     //assert(endpoint == &usb_control_in);
 | ||||||
|     assert(transfer == &_control_in_transfer); |     //assert(transfer == &_control_in_transfer);
 | ||||||
|     usb_debug("_tf_setup_control_ack\n"); |     usb_debug("_tf_setup_control_ack\n"); | ||||||
|     static struct usb_transfer _control_out_transfer; |     static struct usb_transfer _control_out_transfer; | ||||||
|     usb_start_empty_transfer(usb_get_control_out_endpoint(), &_control_out_transfer, 0); |     usb_start_empty_transfer(usb_get_control_out_endpoint(), &_control_out_transfer, 0); | ||||||
|  |  | ||||||
|  | @ -109,7 +109,7 @@ typedef struct _audio_device_config { | ||||||
| } audio_device_config; | } audio_device_config; | ||||||
| 
 | 
 | ||||||
| typedef struct _preprocessing_config { | typedef struct _preprocessing_config { | ||||||
|     fix16_t preamp; |     fix3_28_t preamp; | ||||||
|     int reverse_stereo; |     int reverse_stereo; | ||||||
| } preprocessing_config; | } preprocessing_config; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 ploopyco
						ploopyco