2 * Copyright (C) 2013-2015 Intel Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
27 #include "bat-signal.h"
32 /* update chunk_fmt data to bat */
33 static int update_fmt_to_bat(struct bat *bat, struct chunk_fmt *fmt)
35 bat->channels = fmt->channels;
36 bat->rate = fmt->sample_rate;
37 bat->sample_size = fmt->sample_length / 8;
38 if (bat->sample_size > 4) {
39 fprintf(bat->err, _("Invalid format: sample size=%d\n"),
43 bat->frame_size = fmt->blocks_align;
48 /* calculate frames and update to bat */
49 static int update_frames_to_bat(struct bat *bat,
50 struct wav_chunk_header *header, FILE *fp)
52 /* The number of analyzed captured frames is arbitrarily set to half of
53 the number of frames of the wav file or the number of frames of the
54 wav file when doing direct analysis (--local) */
55 bat->frames = header->length / bat->frame_size;
62 static int read_chunk_fmt(struct bat *bat, char *file, FILE *fp, bool skip,
63 struct wav_chunk_header *header)
67 struct chunk_fmt chunk_fmt;
69 err = fread(&chunk_fmt, sizeof(chunk_fmt), 1, fp);
71 fprintf(bat->err, _("Read chunk fmt error: %s:%zd\n"),
75 /* If the format header is larger, skip the rest */
76 header_skip = header->length - sizeof(chunk_fmt);
77 if (header_skip > 0) {
78 err = fseek(fp, header_skip, SEEK_CUR);
80 fprintf(bat->err, _("Seek fmt header error: %s:%zd\n"),
85 /* If the file is opened for playback, update BAT data;
86 If the file is opened for analysis, no update */
88 err = update_fmt_to_bat(bat, &chunk_fmt);
96 int read_wav_header(struct bat *bat, char *file, FILE *fp, bool skip)
98 struct wav_header riff_wave_header;
99 struct wav_chunk_header chunk_header;
103 /* Read header of RIFF wav file */
104 err = fread(&riff_wave_header, sizeof(riff_wave_header), 1, fp);
106 fprintf(bat->err, _("Read header error: %s:%zd\n"), file, err);
109 if ((riff_wave_header.magic != WAV_RIFF)
110 || (riff_wave_header.type != WAV_WAVE)) {
111 fprintf(bat->err, _("%s is not a riff/wave file\n"), file);
115 /* Read chunks in RIFF wav file */
117 err = fread(&chunk_header, sizeof(chunk_header), 1, fp);
119 fprintf(bat->err, _("Read chunk header error: "));
120 fprintf(bat->err, _("%s:%zd\n"), file, err);
124 switch (chunk_header.type) {
126 /* WAV_FMT chunk, read and analyze */
127 err = read_chunk_fmt(bat, file, fp, skip,
133 /* WAV_DATA chunk, break looping */
134 /* If the file is opened for playback, update BAT data;
135 If the file is opened for analysis, no update */
137 err = update_frames_to_bat(bat, &chunk_header,
142 /* Stop looking for chunks */
146 /* Unknown chunk, skip bytes */
147 err = fseek(fp, chunk_header.length, SEEK_CUR);
149 fprintf(bat->err, _("Fail to skip unknown"));
150 fprintf(bat->err, _(" chunk of %s:%zd\n"),
155 } while (more_chunks);
160 void prepare_wav_info(struct wav_container *wav, struct bat *bat)
162 wav->header.magic = WAV_RIFF;
163 wav->header.type = WAV_WAVE;
164 wav->format.magic = WAV_FMT;
165 wav->format.fmt_size = 16;
166 wav->format.format = WAV_FORMAT_PCM;
167 wav->format.channels = bat->channels;
168 wav->format.sample_rate = bat->rate;
169 wav->format.sample_length = bat->sample_size * 8;
170 wav->format.blocks_align = bat->channels * bat->sample_size;
171 wav->format.bytes_p_second = wav->format.blocks_align * bat->rate;
172 wav->chunk.length = bat->frames * bat->frame_size;
173 wav->chunk.type = WAV_DATA;
174 wav->header.length = (wav->chunk.length) + sizeof(wav->chunk)
175 + sizeof(wav->format) + sizeof(wav->header) - 8;
178 int write_wav_header(FILE *fp, struct wav_container *wav, struct bat *bat)
182 err = fwrite(&wav->header, 1, sizeof(wav->header), fp);
183 if (err != sizeof(wav->header)) {
184 fprintf(bat->err, _("Write file error: header %d\n"), err);
187 err = fwrite(&wav->format, 1, sizeof(wav->format), fp);
188 if (err != sizeof(wav->format)) {
189 fprintf(bat->err, _("Write file error: format %d\n"), err);
192 err = fwrite(&wav->chunk, 1, sizeof(wav->chunk), fp);
193 if (err != sizeof(wav->chunk)) {
194 fprintf(bat->err, _("Write file error: chunk %d\n"), err);
201 /* update wav header when data size changed */
202 int update_wav_header(struct bat *bat, FILE *fp, int bytes)
205 struct wav_container wav;
207 prepare_wav_info(&wav, bat);
208 wav.chunk.length = bytes;
209 wav.header.length = (wav.chunk.length) + sizeof(wav.chunk)
210 + sizeof(wav.format) + sizeof(wav.header) - 8;
212 err = write_wav_header(fp, &wav, bat);
218 * Generate buffer to be played either from input file or from generated data
224 int generate_input_data(struct bat *bat, void *buffer, int bytes, int frames)
229 if (bat->playback.file != NULL) {
230 /* From input file */
234 err = fread(buffer + load, 1, bytes - load, bat->fp);
238 _("End of playing.\n"));
241 } else if (err < bytes - load) {
242 if (ferror(bat->fp)) {
243 fprintf(bat->err, _("Read file error"));
244 fprintf(bat->err, _(": %d\n"), err);
253 /* Generate sine wave */
254 if ((bat->sinus_duration) && (load > bat->sinus_duration))
257 err = generate_sine_wave(bat, frames, buffer);