Allow the user to create fully custom filters.
This commit is contained in:
		
							parent
							
								
									66943e9c84
								
							
						
					
					
						commit
						6c627d22fd
					
				|  | @ -103,10 +103,8 @@ bool validate_filter_configuration(filter_configuration_tlv *filters) | |||
|         case BANDPASSPEAK: | ||||
|         case NOTCH: | ||||
|         case ALLPASS: { | ||||
|             //filter2 *args = (filter2 *)ptr;
 | ||||
|             //printf("Found Filter %d: %0.2f %0.2f\n", args->type, args->f0, args->Q);
 | ||||
|             if (remaining < sizeof(filter2)) { | ||||
|                 printf("Error! Not enough data left for filter2 (%d)..\n", remaining); | ||||
|                 printf("Error! Not enough data left for filter2 (%d)\n", remaining); | ||||
|                 return false; | ||||
|             } | ||||
|             ptr += sizeof(filter2); | ||||
|  | @ -115,15 +113,27 @@ bool validate_filter_configuration(filter_configuration_tlv *filters) | |||
|         case PEAKING: | ||||
|         case LOWSHELF: | ||||
|         case HIGHSHELF: { | ||||
|             //filter3 *args = (filter3 *)ptr;
 | ||||
|             //printf("Found Filter %d: %0.2f %0.2f %0.2f\n", args->type, args->f0, args->db_gain, args->Q);
 | ||||
|             if (remaining < sizeof(filter3)) { | ||||
|                 printf("Error! Not enough data left for filter3 (%d)..\n", remaining); | ||||
|                 printf("Error! Not enough data left for filter3 (%d)\n", remaining); | ||||
|                 return false; | ||||
|             } | ||||
|             ptr += sizeof(filter3); | ||||
|             break; | ||||
|         } | ||||
|         case CUSTOMIIR:  { | ||||
|             filter6 *args = (filter6 *)ptr; | ||||
|             if (remaining < sizeof(filter6)) { | ||||
|                 printf("Error! Not enough data left for filter6 (%d)\n", remaining); | ||||
|                 return false; | ||||
|             } | ||||
|             if (args->a0 == 0.0) { | ||||
|                 printf("Error! The a0 co-efficient of an IIR filter must not be 0.\n"); | ||||
|                 return false; | ||||
|             } | ||||
|             ptr += sizeof(filter6); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         default: | ||||
|             printf("Unknown filter type\n"); | ||||
|             return false; | ||||
|  | @ -164,26 +174,42 @@ void apply_filter_configuration(filter_configuration_tlv *filters) { | |||
|             case PEAKING: INIT_FILTER3(peaking); | ||||
|             case LOWSHELF: INIT_FILTER3(lowshelf); | ||||
|             case HIGHSHELF: INIT_FILTER3(highshelf); | ||||
|             case CUSTOMIIR: { | ||||
|                 filter6 *args = (filter6 *)ptr; | ||||
|                 uint32_t checksum = 0; | ||||
|                 for (int i = 0; i < sizeof(filter6) / 4; i++) checksum ^= ((uint32_t*) args)[i]; | ||||
|                 if (checksum != bqf_filter_checksum[filter_stages]) { | ||||
|                     bqf_filters_left[filter_stages].a0 = fix16_from_dbl(1.0); | ||||
|                     bqf_filters_left[filter_stages].a1 = fix16_from_dbl(args->a1/args->a0); | ||||
|                     bqf_filters_left[filter_stages].a2 = fix16_from_dbl(args->a2/args->a0); | ||||
|                     bqf_filters_left[filter_stages].b0 = fix16_from_dbl(args->b0/args->a0); | ||||
|                     bqf_filters_left[filter_stages].b1 = fix16_from_dbl(args->b1/args->a0); | ||||
|                     bqf_filters_left[filter_stages].b2 = fix16_from_dbl(args->b2/args->a0); | ||||
|                     memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t)); | ||||
|                     bqf_filter_checksum[filter_stages] = checksum; | ||||
|                 } | ||||
|                 ptr += sizeof(filter6); | ||||
|                 type_changed = true; // Always flush our memory
 | ||||
|                 break; | ||||
|             } | ||||
|             default: | ||||
|                 break; | ||||
|         } | ||||
|         filter_stages++; | ||||
|     } | ||||
|         if (type_changed) { | ||||
|             // The memory structure stores the last 2 input samples, we can replay them into
 | ||||
|             // 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 }; | ||||
|             fix16_t right[2] = { bqf_filters_mem_right[filter_stages].x_2, bqf_filters_mem_right[filter_stages].x_1 }; | ||||
| 
 | ||||
|     if (type_changed) { | ||||
|         // The memory structure stores the last 2 input samples, we can replay them into
 | ||||
|         // the new filter rather than starting again from scratch.
 | ||||
|         fix16_t left[2] = { bqf_filters_mem_left[0].x_2, bqf_filters_mem_left[0].x_1 }; | ||||
|         fix16_t right[2] = { bqf_filters_mem_right[0].x_2, bqf_filters_mem_right[0].x_1 }; | ||||
|         for (int i=0; i<filter_stages; i++) { | ||||
|             bqf_memreset(&bqf_filters_mem_left[i]); | ||||
|             bqf_memreset(&bqf_filters_mem_right[i]); | ||||
|             bqf_memreset(&bqf_filters_mem_left[filter_stages]); | ||||
|             bqf_memreset(&bqf_filters_mem_right[filter_stages]); | ||||
| 
 | ||||
|             left[0] = bqf_transform(left[0], &bqf_filters_left[i], &bqf_filters_mem_left[i]); | ||||
|             left[1] = bqf_transform(left[1], &bqf_filters_left[i], &bqf_filters_mem_left[i]); | ||||
|             right[0] = bqf_transform(right[0], &bqf_filters_right[i], &bqf_filters_mem_right[i]); | ||||
|             right[1] = bqf_transform(right[1], &bqf_filters_right[i], &bqf_filters_mem_right[i]); | ||||
|             left[0] = bqf_transform(left[0], &bqf_filters_left[filter_stages], &bqf_filters_mem_left[filter_stages]); | ||||
|             left[1] = bqf_transform(left[1], &bqf_filters_left[filter_stages], &bqf_filters_mem_left[filter_stages]); | ||||
|             right[0] = bqf_transform(right[0], &bqf_filters_right[filter_stages], &bqf_filters_mem_right[filter_stages]); | ||||
|             right[1] = bqf_transform(right[1], &bqf_filters_right[filter_stages], &bqf_filters_mem_right[filter_stages]); | ||||
|         } | ||||
|         filter_stages++; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| #include <stdint.h> | ||||
| 
 | ||||
| #define FLASH_MAGIC 0x2E8AFEDD | ||||
| #define CONFIG_VERSION 1 | ||||
| #define CONFIG_VERSION 2 | ||||
| #define MINIMUM_CONFIG_VERSION 1 | ||||
| 
 | ||||
| enum structure_types { | ||||
|  | @ -65,6 +65,17 @@ typedef struct __attribute__((__packed__)) _filter3 { | |||
|     double Q; | ||||
| } filter3; | ||||
| 
 | ||||
| typedef struct __attribute__((__packed__)) _filter6 { | ||||
|     uint8_t type; | ||||
|     uint8_t reserved[3]; | ||||
|     double a0; | ||||
|     double a1; | ||||
|     double a2; | ||||
|     double b0; | ||||
|     double b1; | ||||
|     double b2; | ||||
| } filter6; | ||||
| 
 | ||||
| enum filter_type { | ||||
|     LOWPASS = 0, | ||||
|     HIGHPASS, | ||||
|  | @ -74,7 +85,8 @@ enum filter_type { | |||
|     ALLPASS, | ||||
|     PEAKING, | ||||
|     LOWSHELF, | ||||
|     HIGHSHELF | ||||
|     HIGHSHELF, | ||||
|     CUSTOMIIR | ||||
| }; | ||||
| 
 | ||||
| typedef struct __attribute__((__packed__)) _flash_header_tlv { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 george-norton
						george-norton