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 38*ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "wav_util.c" 39*ab2c6ae4SMatthias Ringwald 40abc91186SMilanka Ringwald #include <stdint.h> 41abc91186SMilanka Ringwald #include <stdio.h> 42abc91186SMilanka Ringwald #include <stdlib.h> 43abc91186SMilanka Ringwald #include <string.h> 44abc91186SMilanka Ringwald #include <fcntl.h> 45abc91186SMilanka Ringwald #include <unistd.h> 46abc91186SMilanka Ringwald 47abc91186SMilanka Ringwald #include "wav_util.h" 48abc91186SMilanka Ringwald #include "btstack_util.h" 496f91db60SMilanka Ringwald #include "btstack_debug.h" 50abc91186SMilanka Ringwald 51abc91186SMilanka Ringwald static int wav_reader_fd; 52abc91186SMilanka Ringwald static int bytes_per_sample = 2; 53abc91186SMilanka Ringwald 54abc91186SMilanka Ringwald /* Write wav file utils */ 55abc91186SMilanka Ringwald typedef struct wav_writer_state { 56abc91186SMilanka Ringwald FILE * wav_file; 57abc91186SMilanka Ringwald int total_num_samples; 58abc91186SMilanka Ringwald int num_channels; 59abc91186SMilanka Ringwald int sampling_frequency; 60abc91186SMilanka Ringwald int frame_count; 61abc91186SMilanka Ringwald } wav_writer_state_t; 62abc91186SMilanka Ringwald 63abc91186SMilanka Ringwald wav_writer_state_t wav_writer_state; 64abc91186SMilanka Ringwald 65abc91186SMilanka Ringwald 66abc91186SMilanka Ringwald static void little_endian_fstore_16(FILE *wav_file, uint16_t value){ 67abc91186SMilanka Ringwald uint8_t buf[2]; 68abc91186SMilanka Ringwald little_endian_store_16(buf, 0, value); 69abc91186SMilanka Ringwald fwrite(&buf, 1, 2, wav_file); 70abc91186SMilanka Ringwald } 71abc91186SMilanka Ringwald 72abc91186SMilanka Ringwald static void little_endian_fstore_32(FILE *wav_file, uint32_t value){ 73abc91186SMilanka Ringwald uint8_t buf[4]; 74abc91186SMilanka Ringwald little_endian_store_32(buf, 0, value); 75abc91186SMilanka Ringwald fwrite(&buf, 1, 4, wav_file); 76abc91186SMilanka Ringwald } 77abc91186SMilanka Ringwald 78abc91186SMilanka Ringwald static ssize_t __read(int fd, void *buf, size_t count){ 79abc91186SMilanka Ringwald ssize_t len, pos = 0; 80abc91186SMilanka Ringwald 81abc91186SMilanka Ringwald while (count > 0) { 82abc91186SMilanka Ringwald len = read(fd, (int8_t * )buf + pos, count); 83abc91186SMilanka Ringwald if (len <= 0) 84abc91186SMilanka Ringwald return pos; 85abc91186SMilanka Ringwald 86abc91186SMilanka Ringwald count -= len; 87abc91186SMilanka Ringwald pos += len; 88abc91186SMilanka Ringwald } 89abc91186SMilanka Ringwald return pos; 90abc91186SMilanka Ringwald } 91abc91186SMilanka Ringwald 92abc91186SMilanka Ringwald static void write_wav_header(FILE * wav_file, int total_num_samples, int num_channels, int sample_rate){ 93fbc7c9f2SMilanka Ringwald unsigned int write_with_bytes_per_sample = 2; 94abc91186SMilanka Ringwald /* write RIFF header */ 95abc91186SMilanka Ringwald fwrite("RIFF", 1, 4, wav_file); 96abc91186SMilanka Ringwald // num_samples = blocks * subbands 97fbc7c9f2SMilanka Ringwald uint32_t data_bytes = (uint32_t) (write_with_bytes_per_sample * total_num_samples * num_channels); 98abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes + 36); 99abc91186SMilanka Ringwald fwrite("WAVE", 1, 4, wav_file); 100abc91186SMilanka Ringwald 101fbc7c9f2SMilanka Ringwald int byte_rate = sample_rate * num_channels * write_with_bytes_per_sample; 102fbc7c9f2SMilanka Ringwald int bits_per_sample = 8 * write_with_bytes_per_sample; 103abc91186SMilanka Ringwald int block_align = num_channels * bits_per_sample; 104abc91186SMilanka Ringwald int fmt_length = 16; 105abc91186SMilanka Ringwald int fmt_format_tag = 1; // PCM 106abc91186SMilanka Ringwald 107abc91186SMilanka Ringwald /* write fmt chunk */ 108abc91186SMilanka Ringwald fwrite("fmt ", 1, 4, wav_file); 109abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, fmt_length); 110abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, fmt_format_tag); 111abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, num_channels); 112abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, sample_rate); 113abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, byte_rate); 114abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, block_align); 115abc91186SMilanka Ringwald little_endian_fstore_16(wav_file, bits_per_sample); 116abc91186SMilanka Ringwald 117abc91186SMilanka Ringwald /* write data chunk */ 118abc91186SMilanka Ringwald fwrite("data", 1, 4, wav_file); 119abc91186SMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes); 120abc91186SMilanka Ringwald } 121abc91186SMilanka Ringwald 122abc91186SMilanka Ringwald int wav_writer_open(const char * filepath, int num_channels, int sampling_frequency){ 123abc91186SMilanka Ringwald FILE * wav_file = fopen(filepath, "wb"); 124abc91186SMilanka Ringwald if (!wav_file) return 1; 125abc91186SMilanka Ringwald 126abc91186SMilanka Ringwald wav_writer_state.wav_file = wav_file; 127abc91186SMilanka Ringwald wav_writer_state.frame_count = 0; 128abc91186SMilanka Ringwald wav_writer_state.total_num_samples = 0; 129abc91186SMilanka Ringwald wav_writer_state.num_channels = num_channels; 130abc91186SMilanka Ringwald wav_writer_state.sampling_frequency = sampling_frequency; 131abc91186SMilanka Ringwald write_wav_header(wav_writer_state.wav_file, 0, num_channels, sampling_frequency); 132abc91186SMilanka Ringwald return 0; 133abc91186SMilanka Ringwald } 134abc91186SMilanka Ringwald 135abc91186SMilanka Ringwald int wav_writer_close(void){ 136abc91186SMilanka Ringwald rewind(wav_writer_state.wav_file); 137abc91186SMilanka Ringwald write_wav_header(wav_writer_state.wav_file, wav_writer_state.total_num_samples, 138abc91186SMilanka Ringwald wav_writer_state.num_channels, wav_writer_state.sampling_frequency); 139abc91186SMilanka Ringwald fclose(wav_writer_state.wav_file); 140abc91186SMilanka Ringwald return 0; 141abc91186SMilanka Ringwald } 142abc91186SMilanka Ringwald 143abc91186SMilanka Ringwald int wav_writer_write_int8(int num_samples, int8_t * data){ 144abc91186SMilanka Ringwald if (data == NULL) return 1; 145abc91186SMilanka Ringwald int i = 0; 146abc91186SMilanka Ringwald int8_t zero_byte = 0; 147abc91186SMilanka Ringwald for (i=0; i<num_samples; i++){ 148abc91186SMilanka Ringwald fwrite(&zero_byte, 1, 1, wav_writer_state.wav_file); 149abc91186SMilanka Ringwald uint8_t byte_value = (uint8_t)data[i]; 150abc91186SMilanka Ringwald fwrite(&byte_value, 1, 1, wav_writer_state.wav_file); 151abc91186SMilanka Ringwald } 152abc91186SMilanka Ringwald 153abc91186SMilanka Ringwald wav_writer_state.total_num_samples+=num_samples; 154abc91186SMilanka Ringwald wav_writer_state.frame_count++; 155abc91186SMilanka Ringwald return 0; 156abc91186SMilanka Ringwald } 157abc91186SMilanka Ringwald 15892abe7b9SMatthias Ringwald int wav_writer_write_le_int16(int num_samples, int16_t * data){ 159fbc7c9f2SMilanka Ringwald if (data == NULL) return 1; 160fbc7c9f2SMilanka Ringwald fwrite(data, num_samples, 2, wav_writer_state.wav_file); 161fbc7c9f2SMilanka Ringwald 162fbc7c9f2SMilanka Ringwald wav_writer_state.total_num_samples+=num_samples; 163fbc7c9f2SMilanka Ringwald wav_writer_state.frame_count++; 164fbc7c9f2SMilanka Ringwald return 0; 165fbc7c9f2SMilanka Ringwald } 166fbc7c9f2SMilanka Ringwald 16792abe7b9SMatthias Ringwald int wav_writer_write_int16(int num_samples, int16_t * data){ 16892abe7b9SMatthias Ringwald if (btstack_is_little_endian()){ 16992abe7b9SMatthias Ringwald return wav_writer_write_le_int16(num_samples, data); 17092abe7b9SMatthias Ringwald } 17192abe7b9SMatthias Ringwald if (data == NULL) return 1; 17292abe7b9SMatthias Ringwald 17392abe7b9SMatthias Ringwald int i; 17492abe7b9SMatthias Ringwald for (i=0;i<num_samples;i++){ 17592abe7b9SMatthias Ringwald uint16_t sample = btstack_flip_16(data[i]); 17692abe7b9SMatthias Ringwald fwrite(&sample, 1, 2, wav_writer_state.wav_file); 17792abe7b9SMatthias Ringwald } 17892abe7b9SMatthias Ringwald 17992abe7b9SMatthias Ringwald wav_writer_state.total_num_samples+=num_samples; 18092abe7b9SMatthias Ringwald wav_writer_state.frame_count++; 18192abe7b9SMatthias Ringwald return 0; 18292abe7b9SMatthias Ringwald } 18392abe7b9SMatthias Ringwald 184abc91186SMilanka Ringwald int wav_reader_open(const char * filepath){ 185abc91186SMilanka Ringwald wav_reader_fd = open(filepath, O_RDONLY); 186abc91186SMilanka Ringwald if (!wav_reader_fd) { 1876f91db60SMilanka Ringwald log_error("Can't open file %s", filepath); 188abc91186SMilanka Ringwald return 1; 189abc91186SMilanka Ringwald } 190abc91186SMilanka Ringwald 191abc91186SMilanka Ringwald uint8_t buf[40]; 192abc91186SMilanka Ringwald __read(wav_reader_fd, buf, sizeof(buf)); 193abc91186SMilanka Ringwald 194abc91186SMilanka Ringwald int num_channels = little_endian_read_16(buf, 22); 195abc91186SMilanka Ringwald int block_align = little_endian_read_16(buf, 32); 1966f91db60SMilanka Ringwald if (num_channels != 1 && num_channels != 2) { 1976f91db60SMilanka Ringwald log_error("Unexpected num channels %d", num_channels); 1986f91db60SMilanka Ringwald return 1; 1996f91db60SMilanka Ringwald } 200abc91186SMilanka Ringwald bytes_per_sample = block_align/num_channels; 201abc91186SMilanka Ringwald if (bytes_per_sample > 2){ 202abc91186SMilanka Ringwald bytes_per_sample = bytes_per_sample/8; 203abc91186SMilanka Ringwald } 204abc91186SMilanka Ringwald return 0; 205abc91186SMilanka Ringwald } 206abc91186SMilanka Ringwald 207abc91186SMilanka Ringwald int wav_reader_close(void){ 208abc91186SMilanka Ringwald close(wav_reader_fd); 209abc91186SMilanka Ringwald return 0; 210abc91186SMilanka Ringwald } 211abc91186SMilanka Ringwald 212abc91186SMilanka Ringwald // Wav data: 8bit is uint8_t; 16bit is int16 213abc91186SMilanka Ringwald int wav_reader_read_int8(int num_samples, int8_t * data){ 214abc91186SMilanka Ringwald if (!wav_reader_fd) return 1; 215abc91186SMilanka Ringwald int i; 216abc91186SMilanka Ringwald int bytes_read = 0; 217abc91186SMilanka Ringwald 218abc91186SMilanka Ringwald for (i=0; i<num_samples; i++){ 219abc91186SMilanka Ringwald if (bytes_per_sample == 2){ 220abc91186SMilanka Ringwald uint8_t buf[2]; 221abc91186SMilanka Ringwald bytes_read +=__read(wav_reader_fd, &buf, 2); 222abc91186SMilanka Ringwald data[i] = buf[1]; 223abc91186SMilanka Ringwald } else { 224abc91186SMilanka Ringwald uint8_t buf[1]; 225abc91186SMilanka Ringwald bytes_read +=__read(wav_reader_fd, &buf, 1); 226abc91186SMilanka Ringwald data[i] = buf[0] + 128; 227abc91186SMilanka Ringwald } 228abc91186SMilanka Ringwald } 229747ec646SMilanka Ringwald if (bytes_read == num_samples*bytes_per_sample) { 230747ec646SMilanka Ringwald return 0; 231747ec646SMilanka Ringwald } else { 232747ec646SMilanka Ringwald return 1; 233747ec646SMilanka Ringwald } 234abc91186SMilanka Ringwald } 235abc91186SMilanka Ringwald 236fbc7c9f2SMilanka Ringwald int wav_reader_read_int16(int num_samples, int16_t * data){ 237fbc7c9f2SMilanka Ringwald if (!wav_reader_fd) return 1; 238fbc7c9f2SMilanka Ringwald int i; 239fbc7c9f2SMilanka Ringwald int bytes_read = 0; 240fbc7c9f2SMilanka Ringwald for (i=0; i<num_samples; i++){ 241fbc7c9f2SMilanka Ringwald uint8_t buf[2]; 242fbc7c9f2SMilanka Ringwald bytes_read +=__read(wav_reader_fd, &buf, 2); 243fbc7c9f2SMilanka Ringwald data[i] = little_endian_read_16(buf, 0); 244fbc7c9f2SMilanka Ringwald } 245747ec646SMilanka Ringwald if (bytes_read == num_samples*bytes_per_sample) { 246747ec646SMilanka Ringwald return 0; 247747ec646SMilanka Ringwald } else { 248747ec646SMilanka Ringwald return 1; 249747ec646SMilanka Ringwald } 250fbc7c9f2SMilanka Ringwald } 251fbc7c9f2SMilanka Ringwald 252abc91186SMilanka Ringwald 253