Binaural synthesis (confbridge): Adds utils/conf_bridge_binaural_hrir_importer
[asterisk/asterisk.git] / utils / conf_bridge_binaural_hrir_importer.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2016, Digium, Inc.
5  *
6  * Frank Haase <fra.haase@gmail.com>
7  * Dennis Guse <dennis.guse@alumni.tu-berlin.de>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*!
21  * \file
22  * Converts a Head Related Impulse Response (HRIR) database (a multi-channel wave) into a C header file.
23  * HRIR for the left ear and HRIR for right ear have to be interleaved.
24  * No further signal processing is applied (e.g., resampling).
25  *
26  * Info messages are printed to stderror and the generated header file to output.
27  */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <sndfile.h>
33
34 int main (int argc, char **argv)
35 {
36         char *hrir_filename;
37         unsigned int binaural_index_start;
38         unsigned int binaural_index_end;
39
40         SNDFILE *hrir_file;
41         SF_INFO hrir_info;
42         float *hrir_data;
43
44         unsigned int impulse_response_index_start;
45         unsigned int impulse_response_index_end;
46
47         int j;
48         int ir_current;
49
50         if(argc != 4) {
51                 puts("HRIR database to C header file converter.");
52                 puts("Usage: conf_bridge_binaural_hrir_importer HRIR.wav INDEX_START INDEX_END > OUTPUT.h");
53                 puts("Example: conf_bridge_binaural_hrir_importer hrirs.wav 0 180 > ../bridges/bridge_softmix/include/hrirs.h");
54
55                 return -1;
56         }
57
58         /* Parse arguments */
59         hrir_filename = argv[1];
60         binaural_index_start = atoi(argv[2]);
61         binaural_index_end = atoi(argv[3]);
62
63         /* Read HRIR database */
64         hrir_file = sf_open(hrir_filename, SFM_READ, &hrir_info);
65         if(hrir_file == NULL) {
66                 fprintf(stderr, "ERROR: Could not open HRIR database (%s).\n", hrir_filename);
67
68                 return -1;
69         }
70         fprintf(stderr, "INFO: Opened HRIR database (%s) with: number channels: %d; samplerate: %d; samples per channel: %ld\n", hrir_filename, hrir_info.channels, hrir_info.samplerate, hrir_info.frames);
71
72         hrir_data = (float *)malloc(hrir_info.channels * hrir_info.frames * sizeof(float));
73         if(hrir_data == NULL) {
74                 fprintf(stderr, "ERROR: Out of memory!");
75
76                 return -1;
77         }
78
79         /* Channels are interleaved */
80         sf_read_float(hrir_file, hrir_data, hrir_info.channels * hrir_info.frames);
81         sf_close(hrir_file);
82
83         if(binaural_index_start >= binaural_index_end) {
84                 fprintf(stderr, "ERROR: INDEX_START (%d) must be smaller than INDEX_END (%d).", binaural_index_start, binaural_index_end);
85                 free(hrir_data);
86
87                 return -1;
88         }
89
90         if (binaural_index_end * 2 >= hrir_info.channels) {
91                 fprintf(stderr, "ERROR: END_INDEX (%d) is out of range for HRIR database (%s).\n", binaural_index_end, hrir_filename);
92                 free(hrir_data);
93
94                 return -1;
95         }
96
97         /* Convert indices */
98         impulse_response_index_start = 2 * binaural_index_start;
99         impulse_response_index_end = (binaural_index_end + 1) * 2;
100
101         /* Write header */
102         printf("//Used hrirs database: %s\n", hrir_filename);
103         printf("//Start index in database: %d\n", impulse_response_index_start);
104         printf("//End index in database: %d\n", impulse_response_index_end);
105
106         printf("#define HRIRS_IMPULSE_LEN %ld\n", hrir_info.frames);
107         printf("#define HRIRS_IMPULSE_SIZE %d\n", binaural_index_end - binaural_index_start + 1);
108         printf("#define HRIRS_SAMPLE_RATE %d\n", hrir_info.samplerate);
109
110         printf("float hrirs_left[HRIRS_IMPULSE_SIZE][HRIRS_IMPULSE_LEN] = {\n");
111         for (ir_current = impulse_response_index_start; ir_current < impulse_response_index_end; ir_current += 2) {
112                         printf("{");
113
114                         for (j = 0; j < hrir_info.frames - 1; j++) {
115                                 printf("%.16f,", hrir_data[ir_current * hrir_info.frames + j]);
116                         }
117                         /* Write last without trailing "," */
118                         printf("%.16f", hrir_data[ir_current * hrir_info.frames + hrir_info.frames - 1]);
119
120                         if (ir_current + 2 < impulse_response_index_end) {
121                                 printf("},\n");
122                         }       else {
123                                 printf("}};");
124                         }
125         }
126
127         printf("\nfloat hrirs_right[HRIRS_IMPULSE_SIZE][HRIRS_IMPULSE_LEN] = {\n");
128         for (ir_current = impulse_response_index_start + 1; ir_current < impulse_response_index_end + 1; ir_current += 2) {
129                         printf("{");
130
131                         for (j = 0; j < hrir_info.frames - 1; j++) {
132                                 printf("%.16f,", hrir_data[ir_current * hrir_info.frames + j]);
133                         }
134                          /* Write last without trailing "," */
135                         printf("%.16f", hrir_data[ir_current * hrir_info.frames + hrir_info.frames - 1]);
136
137                         if (ir_current + 2 < impulse_response_index_end) {
138                                 printf("},\n");
139                         }       else {
140                                 printf("}};");
141                         }
142         }
143
144         fprintf(stderr, "INFO: Successfully converted: imported %d impulse responses.\n", impulse_response_index_end - impulse_response_index_start);
145         free(hrir_data);
146
147         return 0;
148 }