1abc91186SMilanka Ringwald /* 2abc91186SMilanka Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3abc91186SMilanka Ringwald * 4abc91186SMilanka Ringwald * Redistribution and use in source and binary forms, with or without 5abc91186SMilanka Ringwald * modification, are permitted provided that the following conditions 6abc91186SMilanka Ringwald * are met: 7abc91186SMilanka Ringwald * 8abc91186SMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 9abc91186SMilanka Ringwald * notice, this list of conditions and the following disclaimer. 10abc91186SMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11abc91186SMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 12abc91186SMilanka Ringwald * documentation and/or other materials provided with the distribution. 13abc91186SMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 14abc91186SMilanka Ringwald * contributors may be used to endorse or promote products derived 15abc91186SMilanka Ringwald * from this software without specific prior written permission. 16abc91186SMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 17abc91186SMilanka Ringwald * personal benefit and not for any commercial purpose or for 18abc91186SMilanka Ringwald * monetary gain. 19abc91186SMilanka Ringwald * 20abc91186SMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21abc91186SMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22abc91186SMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23abc91186SMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24abc91186SMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25abc91186SMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26abc91186SMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27abc91186SMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28abc91186SMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29abc91186SMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30abc91186SMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31abc91186SMilanka Ringwald * SUCH DAMAGE. 32abc91186SMilanka Ringwald * 33abc91186SMilanka Ringwald * Please inquire about commercial licensing options at 34abc91186SMilanka Ringwald * [email protected] 35abc91186SMilanka Ringwald * 36abc91186SMilanka Ringwald */ 37abc91186SMilanka Ringwald 38abc91186SMilanka Ringwald #include <stdint.h> 39abc91186SMilanka Ringwald #include <stdio.h> 40abc91186SMilanka Ringwald #include <stdlib.h> 41abc91186SMilanka Ringwald #include <string.h> 42abc91186SMilanka Ringwald #include <fcntl.h> 43abc91186SMilanka Ringwald #include <unistd.h> 44abc91186SMilanka Ringwald 45abc91186SMilanka Ringwald #include "wav_util.h" 46abc91186SMilanka Ringwald #include "btstack_util.h" 47abc91186SMilanka Ringwald 48*fbc7c9f2SMilanka Ringwald static const uint8_t sine_uint8[] = { 49abc91186SMilanka Ringwald 0, 15, 31, 46, 61, 74, 86, 97, 107, 114, 50abc91186SMilanka Ringwald 120, 124, 126, 126, 124, 120, 114, 107, 97, 86, 51abc91186SMilanka Ringwald 74, 61, 46, 31, 15, 0, 241, 225, 210, 195, 52abc91186SMilanka Ringwald 182, 170, 159, 149, 142, 136, 132, 130, 130, 132, 53abc91186SMilanka Ringwald 136, 142, 149, 159, 170, 182, 195, 210, 225, 241, 54abc91186SMilanka Ringwald }; 55*fbc7c9f2SMilanka Ringwald 56*fbc7c9f2SMilanka Ringwald 57*fbc7c9f2SMilanka Ringwald // input signal: pre-computed sine wave, 160 Hz at 16000 kHz 58*fbc7c9f2SMilanka Ringwald static const int16_t sine_int16[] = { 59*fbc7c9f2SMilanka Ringwald 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 60*fbc7c9f2SMilanka Ringwald 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 61*fbc7c9f2SMilanka Ringwald 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 62*fbc7c9f2SMilanka Ringwald 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 63*fbc7c9f2SMilanka Ringwald 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 64*fbc7c9f2SMilanka Ringwald 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 65*fbc7c9f2SMilanka Ringwald -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 66*fbc7c9f2SMilanka Ringwald -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 67*fbc7c9f2SMilanka Ringwald -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 68*fbc7c9f2SMilanka Ringwald -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 69*fbc7c9f2SMilanka Ringwald }; 70*fbc7c9f2SMilanka Ringwald 71abc91186SMilanka Ringwald static int phase = 0; 72abc91186SMilanka Ringwald 73abc91186SMilanka Ringwald static int wav_reader_fd; 74abc91186SMilanka Ringwald static int bytes_per_sample = 2; 75abc91186SMilanka Ringwald 76abc91186SMilanka Ringwald /* Write wav file utils */ 77abc91186SMilanka Ringwald typedef struct wav_writer_state { 78abc91186SMilanka Ringwald FILE * wav_file; 79abc91186SMilanka Ringwald int total_num_samples; 80abc91186SMilanka Ringwald int num_channels; 81abc91186SMilanka Ringwald int sampling_frequency; 82abc91186SMilanka Ringwald int frame_count; 83abc91186SMilanka Ringwald } wav_writer_state_t; 84abc91186SMilanka Ringwald 85abc91186SMilanka Ringwald wav_writer_state_t wav_writer_state; 86abc91186SMilanka Ringwald 87abc91186SMilanka Ringwald 88abc91186SMilanka Ringwald static void little_endian_fstore_16(FILE *wav_file, uint16_t value){ 89abc91186SMilanka Ringwald uint8_t buf[2]; 90abc91186SMilanka Ringwald little_endian_store_16(buf, 0, value); 91abc91186SMilanka Ringwald fwrite(&buf, 1, 2, wav_file); 92abc91186SMilanka Ringwald } 93abc91186SMilanka Ringwald 94abc91186SMilanka Ringwald static void little_endian_fstore_32(FILE *wav_file, uint32_t value){ 95abc91186SMilanka Ringwald uint8_t buf[4]; 96abc91186SMilanka Ringwald little_endian_store_32(buf, 0, value); 97abc91186SMilanka Ringwald fwrite(&buf, 1, 4, wav_file); 98abc91186SMilanka Ringwald } 99abc91186SMilanka Ringwald 100abc91186SMilanka Ringwald static ssize_t __read(int fd, void *buf, size_t count){ 101abc91186SMilanka Ringwald ssize_t len, pos = 0; 102abc91186SMilanka Ringwald 103abc91186SMilanka Ringwald while (count > 0) { 104abc91186SMilanka Ringwald len = read(fd, (int8_t * )buf + pos, count); 105abc91186SMilanka Ringwald if (len <= 0) 106abc91186SMilanka Ringwald return pos; 107abc91186SMilanka Ringwald 108abc91186SMilanka Ringwald count -= len; 109abc91186SMilanka Ringwald pos += len; 110abc91186SMilanka Ringwald } 111abc91186SMilanka Ringwald return pos; 112abc91186SMilanka Ringwald } 113abc91186SMilanka Ringwald 114abc91186SMilanka Ringwald static void write_wav_header(FILE * wav_file, int total_num_samples, int num_channels, int sample_rate){ 115*fbc7c9f2SMilanka Ringwald unsigned int write_with_bytes_per_sample = 2; 116abc91186SMilanka Ringwald /* write RIFF header */ 117abc91186SMilanka Ringwald fwrite("RIFF", 1, 4, wav_file); 118abc91186SMilanka Ringwald // num_samples = blocks * subbands 119*fbc7c9f2SMilanka Ringwald uint32_t data_bytes = (uint32_t) (write_with_bytes_per_sample * total_num_samples * num_channels); 120abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes + 36); 121abc91186SMilanka Ringwald fwrite("WAVE", 1, 4, wav_file); 122abc91186SMilanka Ringwald 123*fbc7c9f2SMilanka Ringwald int byte_rate = sample_rate * num_channels * write_with_bytes_per_sample; 124*fbc7c9f2SMilanka Ringwald int bits_per_sample = 8 * write_with_bytes_per_sample; 125abc91186SMilanka Ringwald int block_align = num_channels * bits_per_sample; 126abc91186SMilanka Ringwald int fmt_length = 16; 127abc91186SMilanka Ringwald int fmt_format_tag = 1; // PCM 128abc91186SMilanka Ringwald 129abc91186SMilanka Ringwald /* write fmt chunk */ 130abc91186SMilanka Ringwald fwrite("fmt ", 1, 4, wav_file); 131abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, fmt_length); 132abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, fmt_format_tag); 133abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, num_channels); 134abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, sample_rate); 135abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, byte_rate); 136abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, block_align); 137abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, bits_per_sample); 138abc91186SMilanka Ringwald 139abc91186SMilanka Ringwald /* write data chunk */ 140abc91186SMilanka Ringwald fwrite("data", 1, 4, wav_file); 141abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes); 142abc91186SMilanka Ringwald } 143abc91186SMilanka Ringwald 144abc91186SMilanka Ringwald int wav_writer_open(const char * filepath, int num_channels, int sampling_frequency){ 145abc91186SMilanka Ringwald FILE * wav_file = fopen(filepath, "wb"); 146abc91186SMilanka Ringwald if (!wav_file) return 1; 147abc91186SMilanka Ringwald 148abc91186SMilanka Ringwald wav_writer_state.wav_file = wav_file; 149abc91186SMilanka Ringwald wav_writer_state.frame_count = 0; 150abc91186SMilanka Ringwald wav_writer_state.total_num_samples = 0; 151abc91186SMilanka Ringwald wav_writer_state.num_channels = num_channels; 152abc91186SMilanka Ringwald wav_writer_state.sampling_frequency = sampling_frequency; 153abc91186SMilanka Ringwald write_wav_header(wav_writer_state.wav_file, 0, num_channels, sampling_frequency); 154abc91186SMilanka Ringwald return 0; 155abc91186SMilanka Ringwald } 156abc91186SMilanka Ringwald 157abc91186SMilanka Ringwald int wav_writer_close(void){ 158abc91186SMilanka Ringwald rewind(wav_writer_state.wav_file); 159abc91186SMilanka Ringwald write_wav_header(wav_writer_state.wav_file, wav_writer_state.total_num_samples, 160abc91186SMilanka Ringwald wav_writer_state.num_channels, wav_writer_state.sampling_frequency); 161abc91186SMilanka Ringwald fclose(wav_writer_state.wav_file); 162abc91186SMilanka Ringwald return 0; 163abc91186SMilanka Ringwald } 164abc91186SMilanka Ringwald 165abc91186SMilanka Ringwald int wav_writer_write_int8(int num_samples, int8_t * data){ 166abc91186SMilanka Ringwald if (data == NULL) return 1; 167abc91186SMilanka Ringwald int i = 0; 168abc91186SMilanka Ringwald int8_t zero_byte = 0; 169abc91186SMilanka Ringwald for (i=0; i<num_samples; i++){ 170abc91186SMilanka Ringwald fwrite(&zero_byte, 1, 1, wav_writer_state.wav_file); 171abc91186SMilanka Ringwald uint8_t byte_value = (uint8_t)data[i]; 172abc91186SMilanka Ringwald fwrite(&byte_value, 1, 1, wav_writer_state.wav_file); 173abc91186SMilanka Ringwald } 174abc91186SMilanka Ringwald 175abc91186SMilanka Ringwald wav_writer_state.total_num_samples+=num_samples; 176abc91186SMilanka Ringwald wav_writer_state.frame_count++; 177abc91186SMilanka Ringwald return 0; 178abc91186SMilanka Ringwald } 179abc91186SMilanka Ringwald 180*fbc7c9f2SMilanka Ringwald int wav_writer_write_int16(int num_samples, int16_t * data){ 181*fbc7c9f2SMilanka Ringwald if (data == NULL) return 1; 182*fbc7c9f2SMilanka Ringwald fwrite(data, num_samples, 2, wav_writer_state.wav_file); 183*fbc7c9f2SMilanka Ringwald 184*fbc7c9f2SMilanka Ringwald wav_writer_state.total_num_samples+=num_samples; 185*fbc7c9f2SMilanka Ringwald wav_writer_state.frame_count++; 186*fbc7c9f2SMilanka Ringwald return 0; 187*fbc7c9f2SMilanka Ringwald } 188*fbc7c9f2SMilanka Ringwald 189abc91186SMilanka Ringwald int wav_reader_open(const char * filepath){ 190abc91186SMilanka Ringwald wav_reader_fd = open(filepath, O_RDONLY); 191abc91186SMilanka Ringwald if (!wav_reader_fd) { 192abc91186SMilanka Ringwald printf("Can't open file %s", filepath); 193abc91186SMilanka Ringwald return 1; 194abc91186SMilanka Ringwald } 195abc91186SMilanka Ringwald 196abc91186SMilanka Ringwald uint8_t buf[40]; 197abc91186SMilanka Ringwald __read(wav_reader_fd, buf, sizeof(buf)); 198abc91186SMilanka Ringwald 199abc91186SMilanka Ringwald int num_channels = little_endian_read_16(buf, 22); 200abc91186SMilanka Ringwald int block_align = little_endian_read_16(buf, 32); 201abc91186SMilanka Ringwald bytes_per_sample = block_align/num_channels; 202abc91186SMilanka Ringwald if (bytes_per_sample > 2){ 203abc91186SMilanka Ringwald bytes_per_sample = bytes_per_sample/8; 204abc91186SMilanka Ringwald } 205abc91186SMilanka Ringwald return 0; 206abc91186SMilanka Ringwald } 207abc91186SMilanka Ringwald 208abc91186SMilanka Ringwald int wav_reader_close(void){ 209abc91186SMilanka Ringwald close(wav_reader_fd); 210abc91186SMilanka Ringwald return 0; 211abc91186SMilanka Ringwald } 212abc91186SMilanka Ringwald 213abc91186SMilanka Ringwald // Wav data: 8bit is uint8_t; 16bit is int16 214abc91186SMilanka Ringwald int wav_reader_read_int8(int num_samples, int8_t * data){ 215abc91186SMilanka Ringwald if (!wav_reader_fd) return 1; 216abc91186SMilanka Ringwald int i; 217abc91186SMilanka Ringwald int bytes_read = 0; 218abc91186SMilanka Ringwald 219abc91186SMilanka Ringwald for (i=0; i<num_samples; i++){ 220abc91186SMilanka Ringwald if (bytes_per_sample == 2){ 221abc91186SMilanka Ringwald uint8_t buf[2]; 222abc91186SMilanka Ringwald bytes_read +=__read(wav_reader_fd, &buf, 2); 223abc91186SMilanka Ringwald data[i] = buf[1]; 224abc91186SMilanka Ringwald } else { 225abc91186SMilanka Ringwald uint8_t buf[1]; 226abc91186SMilanka Ringwald bytes_read +=__read(wav_reader_fd, &buf, 1); 227abc91186SMilanka Ringwald data[i] = buf[0] + 128; 228abc91186SMilanka Ringwald } 229abc91186SMilanka Ringwald } 230abc91186SMilanka Ringwald return bytes_read == num_samples*bytes_per_sample; 231abc91186SMilanka Ringwald } 232abc91186SMilanka Ringwald 233*fbc7c9f2SMilanka Ringwald int wav_reader_read_int16(int num_samples, int16_t * data){ 234*fbc7c9f2SMilanka Ringwald if (!wav_reader_fd) return 1; 235*fbc7c9f2SMilanka Ringwald int i; 236*fbc7c9f2SMilanka Ringwald int bytes_read = 0; 237*fbc7c9f2SMilanka Ringwald for (i=0; i<num_samples; i++){ 238*fbc7c9f2SMilanka Ringwald uint8_t buf[2]; 239*fbc7c9f2SMilanka Ringwald bytes_read +=__read(wav_reader_fd, &buf, 2); 240*fbc7c9f2SMilanka Ringwald data[i] = little_endian_read_16(buf, 0); 241*fbc7c9f2SMilanka Ringwald } 242*fbc7c9f2SMilanka Ringwald return bytes_read == num_samples*bytes_per_sample; 243*fbc7c9f2SMilanka Ringwald } 244*fbc7c9f2SMilanka Ringwald 245abc91186SMilanka Ringwald void wav_synthesize_sine_wave_int8(int num_samples, int8_t * data){ 246abc91186SMilanka Ringwald int i; 247abc91186SMilanka Ringwald for (i=0; i<num_samples; i++){ 248*fbc7c9f2SMilanka Ringwald data[i] = (int8_t)sine_uint8[phase]; 249abc91186SMilanka Ringwald phase++; 250*fbc7c9f2SMilanka Ringwald if (phase >= sizeof(sine_uint8)) phase = 0; 251*fbc7c9f2SMilanka Ringwald } 252*fbc7c9f2SMilanka Ringwald } 253*fbc7c9f2SMilanka Ringwald 254*fbc7c9f2SMilanka Ringwald void wav_synthesize_sine_wave_int16(int num_samples, int16_t * data){ 255*fbc7c9f2SMilanka Ringwald int i; 256*fbc7c9f2SMilanka Ringwald for (i=0; i < num_samples; i++){ 257*fbc7c9f2SMilanka Ringwald data[i] = sine_int16[phase++]; 258*fbc7c9f2SMilanka Ringwald if (phase >= (sizeof(sine_int16) / sizeof(int16_t))){ 259*fbc7c9f2SMilanka Ringwald phase = 0; 260*fbc7c9f2SMilanka Ringwald } 261abc91186SMilanka Ringwald } 262abc91186SMilanka Ringwald } 263abc91186SMilanka Ringwald 264