1b815c7f3Sopenharmony_ci/* 2b815c7f3Sopenharmony_ci** Copyright (C) 2009-2015 Erik de Castro Lopo <erikd@mega-nerd.com> 3b815c7f3Sopenharmony_ci** 4b815c7f3Sopenharmony_ci** All rights reserved. 5b815c7f3Sopenharmony_ci** 6b815c7f3Sopenharmony_ci** Redistribution and use in source and binary forms, with or without 7b815c7f3Sopenharmony_ci** modification, are permitted provided that the following conditions are 8b815c7f3Sopenharmony_ci** met: 9b815c7f3Sopenharmony_ci** 10b815c7f3Sopenharmony_ci** * Redistributions of source code must retain the above copyright 11b815c7f3Sopenharmony_ci** notice, this list of conditions and the following disclaimer. 12b815c7f3Sopenharmony_ci** * Redistributions in binary form must reproduce the above copyright 13b815c7f3Sopenharmony_ci** notice, this list of conditions and the following disclaimer in 14b815c7f3Sopenharmony_ci** the documentation and/or other materials provided with the 15b815c7f3Sopenharmony_ci** distribution. 16b815c7f3Sopenharmony_ci** * Neither the author nor the names of any contributors may be used 17b815c7f3Sopenharmony_ci** to endorse or promote products derived from this software without 18b815c7f3Sopenharmony_ci** specific prior written permission. 19b815c7f3Sopenharmony_ci** 20b815c7f3Sopenharmony_ci** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21b815c7f3Sopenharmony_ci** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22b815c7f3Sopenharmony_ci** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23b815c7f3Sopenharmony_ci** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24b815c7f3Sopenharmony_ci** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25b815c7f3Sopenharmony_ci** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26b815c7f3Sopenharmony_ci** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27b815c7f3Sopenharmony_ci** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28b815c7f3Sopenharmony_ci** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29b815c7f3Sopenharmony_ci** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 30b815c7f3Sopenharmony_ci** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b815c7f3Sopenharmony_ci*/ 32b815c7f3Sopenharmony_ci 33b815c7f3Sopenharmony_ci#include <stdio.h> 34b815c7f3Sopenharmony_ci#include <stdlib.h> 35b815c7f3Sopenharmony_ci#include <string.h> 36b815c7f3Sopenharmony_ci#include <sndfile.h> 37b815c7f3Sopenharmony_ci 38b815c7f3Sopenharmony_ci#include "common.h" 39b815c7f3Sopenharmony_ci 40b815c7f3Sopenharmony_ci#define BUFFER_LEN 4096 41b815c7f3Sopenharmony_ci#define MAX_INPUTS 16 42b815c7f3Sopenharmony_ci 43b815c7f3Sopenharmony_ci 44b815c7f3Sopenharmony_citypedef struct 45b815c7f3Sopenharmony_ci{ SNDFILE * infile [MAX_INPUTS] ; 46b815c7f3Sopenharmony_ci SNDFILE * outfile ; 47b815c7f3Sopenharmony_ci 48b815c7f3Sopenharmony_ci union 49b815c7f3Sopenharmony_ci { double d [BUFFER_LEN] ; 50b815c7f3Sopenharmony_ci int i [BUFFER_LEN] ; 51b815c7f3Sopenharmony_ci } din ; 52b815c7f3Sopenharmony_ci 53b815c7f3Sopenharmony_ci union 54b815c7f3Sopenharmony_ci 55b815c7f3Sopenharmony_ci { double d [MAX_INPUTS * BUFFER_LEN] ; 56b815c7f3Sopenharmony_ci int i [MAX_INPUTS * BUFFER_LEN] ; 57b815c7f3Sopenharmony_ci } dout ; 58b815c7f3Sopenharmony_ci 59b815c7f3Sopenharmony_ci int channels ; 60b815c7f3Sopenharmony_ci} STATE ; 61b815c7f3Sopenharmony_ci 62b815c7f3Sopenharmony_ci 63b815c7f3Sopenharmony_cistatic void print_usage (void) ; 64b815c7f3Sopenharmony_cistatic void interleave_int (STATE * state) ; 65b815c7f3Sopenharmony_cistatic void interleave_double (STATE * state) ; 66b815c7f3Sopenharmony_ci 67b815c7f3Sopenharmony_ci 68b815c7f3Sopenharmony_ciint 69b815c7f3Sopenharmony_cimain (int argc, char **argv) 70b815c7f3Sopenharmony_ci{ STATE *state = NULL ; 71b815c7f3Sopenharmony_ci SF_INFO sfinfo ; 72b815c7f3Sopenharmony_ci int k, double_merge = 0 ; 73b815c7f3Sopenharmony_ci int ret = 1 ; 74b815c7f3Sopenharmony_ci 75b815c7f3Sopenharmony_ci if (argc < 5) 76b815c7f3Sopenharmony_ci { if (argc > 1) 77b815c7f3Sopenharmony_ci puts ("\nError : need at least 2 input files.") ; 78b815c7f3Sopenharmony_ci print_usage () ; 79b815c7f3Sopenharmony_ci goto cleanup ; 80b815c7f3Sopenharmony_ci } ; 81b815c7f3Sopenharmony_ci 82b815c7f3Sopenharmony_ci if (strcmp (argv [argc - 2], "-o") != 0) 83b815c7f3Sopenharmony_ci { puts ("\nError : second last command line parameter should be '-o'.\n") ; 84b815c7f3Sopenharmony_ci print_usage () ; 85b815c7f3Sopenharmony_ci goto cleanup ; 86b815c7f3Sopenharmony_ci } ; 87b815c7f3Sopenharmony_ci 88b815c7f3Sopenharmony_ci if (argc - 3 > MAX_INPUTS) 89b815c7f3Sopenharmony_ci { printf ("\nError : Cannot handle more than %d input channels.\n\n", MAX_INPUTS) ; 90b815c7f3Sopenharmony_ci goto cleanup ; 91b815c7f3Sopenharmony_ci } ; 92b815c7f3Sopenharmony_ci 93b815c7f3Sopenharmony_ci state = calloc (1, sizeof (STATE)) ; 94b815c7f3Sopenharmony_ci if (state == NULL) 95b815c7f3Sopenharmony_ci { puts ("\nError : out of memory.\n") ; 96b815c7f3Sopenharmony_ci goto cleanup ; 97b815c7f3Sopenharmony_ci } ; 98b815c7f3Sopenharmony_ci 99b815c7f3Sopenharmony_ci memset (&sfinfo, 0, sizeof (sfinfo)) ; 100b815c7f3Sopenharmony_ci 101b815c7f3Sopenharmony_ci for (k = 1 ; k < argc - 2 ; k++) 102b815c7f3Sopenharmony_ci { 103b815c7f3Sopenharmony_ci if ((state->infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL) 104b815c7f3Sopenharmony_ci { printf ("\nError : Not able to open input file '%s'\n%s\n", argv [k], sf_strerror (NULL)) ; 105b815c7f3Sopenharmony_ci goto cleanup ; 106b815c7f3Sopenharmony_ci } ; 107b815c7f3Sopenharmony_ci 108b815c7f3Sopenharmony_ci if (sfinfo.channels != 1) 109b815c7f3Sopenharmony_ci { printf ("\bError : Input file '%s' should be mono (has %d channels).\n", argv [k], sfinfo.channels) ; 110b815c7f3Sopenharmony_ci goto cleanup ; 111b815c7f3Sopenharmony_ci } ; 112b815c7f3Sopenharmony_ci 113b815c7f3Sopenharmony_ci switch (sfinfo.format & SF_FORMAT_SUBMASK) 114b815c7f3Sopenharmony_ci { case SF_FORMAT_FLOAT : 115b815c7f3Sopenharmony_ci case SF_FORMAT_DOUBLE : 116b815c7f3Sopenharmony_ci case SF_FORMAT_VORBIS : 117b815c7f3Sopenharmony_ci double_merge = 1 ; 118b815c7f3Sopenharmony_ci break ; 119b815c7f3Sopenharmony_ci 120b815c7f3Sopenharmony_ci default : 121b815c7f3Sopenharmony_ci break ; 122b815c7f3Sopenharmony_ci } ; 123b815c7f3Sopenharmony_ci 124b815c7f3Sopenharmony_ci state->channels ++ ; 125b815c7f3Sopenharmony_ci } ; 126b815c7f3Sopenharmony_ci 127b815c7f3Sopenharmony_ci sfinfo.channels = state->channels ; 128b815c7f3Sopenharmony_ci sfinfo.format = sfe_file_type_of_ext (argv [argc - 1], sfinfo.format) ; 129b815c7f3Sopenharmony_ci 130b815c7f3Sopenharmony_ci if ((state->outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) 131b815c7f3Sopenharmony_ci { printf ("Not able to open output file '%s'\n%s\n", argv [argc - 1], sf_strerror (NULL)) ; 132b815c7f3Sopenharmony_ci goto cleanup ; 133b815c7f3Sopenharmony_ci } ; 134b815c7f3Sopenharmony_ci 135b815c7f3Sopenharmony_ci if (double_merge) 136b815c7f3Sopenharmony_ci interleave_double (state) ; 137b815c7f3Sopenharmony_ci else 138b815c7f3Sopenharmony_ci interleave_int (state) ; 139b815c7f3Sopenharmony_ci 140b815c7f3Sopenharmony_ci ret = 0 ; 141b815c7f3Sopenharmony_ci 142b815c7f3Sopenharmony_cicleanup : 143b815c7f3Sopenharmony_ci 144b815c7f3Sopenharmony_ci if (state != NULL) 145b815c7f3Sopenharmony_ci { for (k = 0 ; k < MAX_INPUTS ; k++) 146b815c7f3Sopenharmony_ci if (state->infile [k] != NULL) 147b815c7f3Sopenharmony_ci sf_close (state->infile [k]) ; 148b815c7f3Sopenharmony_ci sf_close (state->outfile) ; 149b815c7f3Sopenharmony_ci } 150b815c7f3Sopenharmony_ci 151b815c7f3Sopenharmony_ci free (state) ; 152b815c7f3Sopenharmony_ci 153b815c7f3Sopenharmony_ci return ret ; 154b815c7f3Sopenharmony_ci} /* main */ 155b815c7f3Sopenharmony_ci 156b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------ 157b815c7f3Sopenharmony_ci*/ 158b815c7f3Sopenharmony_ci 159b815c7f3Sopenharmony_ci 160b815c7f3Sopenharmony_cistatic void 161b815c7f3Sopenharmony_ciprint_usage (void) 162b815c7f3Sopenharmony_ci{ puts ("\nUsage : sndfile-interleave <input 1> <input 2> ... -o <output file>\n") ; 163b815c7f3Sopenharmony_ci puts ("Merge two or more mono files into a single multi-channel file.\n") ; 164b815c7f3Sopenharmony_ci printf ("Using %s.\n\n", sf_version_string ()) ; 165b815c7f3Sopenharmony_ci} /* print_usage */ 166b815c7f3Sopenharmony_ci 167b815c7f3Sopenharmony_ci 168b815c7f3Sopenharmony_cistatic void 169b815c7f3Sopenharmony_ciinterleave_int (STATE * state) 170b815c7f3Sopenharmony_ci{ int max_read_len, read_len ; 171b815c7f3Sopenharmony_ci int ch, k ; 172b815c7f3Sopenharmony_ci 173b815c7f3Sopenharmony_ci do 174b815c7f3Sopenharmony_ci { max_read_len = 0 ; 175b815c7f3Sopenharmony_ci 176b815c7f3Sopenharmony_ci for (ch = 0 ; ch < state->channels ; ch ++) 177b815c7f3Sopenharmony_ci { read_len = (int) sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ; 178b815c7f3Sopenharmony_ci if (read_len < BUFFER_LEN) 179b815c7f3Sopenharmony_ci memset (state->din.i + read_len, 0, sizeof (state->din.i [0]) * (BUFFER_LEN - read_len)) ; 180b815c7f3Sopenharmony_ci 181b815c7f3Sopenharmony_ci for (k = 0 ; k < BUFFER_LEN ; k++) 182b815c7f3Sopenharmony_ci state->dout.i [k * state->channels + ch] = state->din.i [k] ; 183b815c7f3Sopenharmony_ci 184b815c7f3Sopenharmony_ci max_read_len = MAX (max_read_len, read_len) ; 185b815c7f3Sopenharmony_ci } ; 186b815c7f3Sopenharmony_ci 187b815c7f3Sopenharmony_ci sf_writef_int (state->outfile, state->dout.i, max_read_len) ; 188b815c7f3Sopenharmony_ci } 189b815c7f3Sopenharmony_ci while (max_read_len > 0) ; 190b815c7f3Sopenharmony_ci 191b815c7f3Sopenharmony_ci} /* interleave_int */ 192b815c7f3Sopenharmony_ci 193b815c7f3Sopenharmony_ci 194b815c7f3Sopenharmony_cistatic void 195b815c7f3Sopenharmony_ciinterleave_double (STATE * state) 196b815c7f3Sopenharmony_ci{ int max_read_len, read_len ; 197b815c7f3Sopenharmony_ci int ch, k ; 198b815c7f3Sopenharmony_ci 199b815c7f3Sopenharmony_ci do 200b815c7f3Sopenharmony_ci { max_read_len = 0 ; 201b815c7f3Sopenharmony_ci 202b815c7f3Sopenharmony_ci for (ch = 0 ; ch < state->channels ; ch ++) 203b815c7f3Sopenharmony_ci { read_len = (int) sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ; 204b815c7f3Sopenharmony_ci if (read_len < BUFFER_LEN) 205b815c7f3Sopenharmony_ci memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ; 206b815c7f3Sopenharmony_ci 207b815c7f3Sopenharmony_ci for (k = 0 ; k < BUFFER_LEN ; k++) 208b815c7f3Sopenharmony_ci state->dout.d [k * state->channels + ch] = state->din.d [k] ; 209b815c7f3Sopenharmony_ci 210b815c7f3Sopenharmony_ci max_read_len = MAX (max_read_len, read_len) ; 211b815c7f3Sopenharmony_ci } ; 212b815c7f3Sopenharmony_ci 213b815c7f3Sopenharmony_ci sf_writef_double (state->outfile, state->dout.d, max_read_len) ; 214b815c7f3Sopenharmony_ci } 215b815c7f3Sopenharmony_ci while (max_read_len > 0) ; 216b815c7f3Sopenharmony_ci 217b815c7f3Sopenharmony_ci} /* interleave_double */ 218