gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
Sox.C
Go to the documentation of this file.
1 /* This file was contributed by Deqx.com
2  Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
3  This file is part of GTK+ IOStream class set
4 
5  GTK+ IOStream is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  GTK+ IOStream is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You have received a copy of the GNU General Public License
16  along with GTK+ IOStream
17 */
18 
19 #if !defined(_MSC_VER) && !defined(__CYGWIN__)
20 #include "Sox.H"
21 #else
22 // Note : Microsoft doesn't understand the different between upper and lower case in file names.
23 // on microsoft, you have to manually rename Sox.H to SoxWindows.H
24 #include "SoxWindows.H"
25 #endif
26 
27 #include <fstream>
28 #include <sox.h>
29 #include <stdio.h>
30 //#include <valarray>
31 
32 using namespace Eigen;
33 
34 template<typename FP_TYPE_>
36  sox_globals.output_message_handler = output_message; // setup the message handler
37  sox_globals.verbosity = 1;
38 
39  assert(sox_init() == SOX_SUCCESS); // init the sox library
40  in=out=NULL;
41 }
42 
43 template<typename FP_TYPE_>
45  close(in); // ensure all memory is destroyed as required
46  close(out);
47  sox_quit();
48 }
49 
50 template<typename FP_TYPE_>
51 int Sox<FP_TYPE_>::close(bool inputFile) {
52  int retVal=NO_ERROR;
53  if (inputFile) {
54  if (in) {
55  if (sox_close(in)!=SOX_SUCCESS)
56  retVal=SOX_CLOSE_FILE_ERROR;
57  in=NULL;
58  }
59  } else {
60  if (out) {
61  if (sox_close(out)!=SOX_SUCCESS)
62  retVal=SOX_CLOSE_FILE_ERROR;
63  out=NULL;
64  }
65  }
66  return retVal;
67 }
68 
69 template<typename FP_TYPE_>
70 int Sox<FP_TYPE_>::openRead(string fileName) {
71  bool inputFile=true;
72  close(inputFile);
73 
74  in = sox_open_read(fileName.c_str(), NULL, NULL, NULL);
75  if (!in)
77 
78  // try to get the intended max value
79  typedef std::numeric_limits<double> Info;
80  maxVal=Info::quiet_NaN();
81  ifstream maxFile((fileName+".max").c_str());
82  if (!maxFile)
84  char maxValStr[256];
85  maxFile>>maxValStr;
86  maxVal=(float)::atof(maxValStr);
87  maxFile.close();
88  return 0;
89 }
90 
91 #include <iostream>
92 
93 template<typename FP_TYPE_>
94 int Sox<FP_TYPE_>::openRead(intptr_t buffer, size_t len){
95  bool inputFile=true;
96  close(inputFile);
97 
98  // for (int i=0;i<len;i++)
99  // std::cout<<(int)((char*)buffer)[i]<<'\t';
100  // std::cout<<std::endl;
101 
102  in = sox_open_mem_read((void*)buffer, len, NULL, NULL, NULL);
103  if (!in)
105 
106  // No defined max value, user has to set manually - indicate
107  typedef std::numeric_limits<double> Info;
108  maxVal=Info::quiet_NaN();
110 }
111 
112 template<typename FP_TYPE_>
113 void Sox<FP_TYPE_>::output_message(unsigned level, const char *filename, const char *fmt, va_list ap) {
114  char const * const str[] = {"FAIL", "WARN", "INFO", "DBUG"};
115  if (sox_globals.verbosity >= level) {
116  char base_name[128];
117  sox_basename(base_name, sizeof(base_name), filename);
118  //fprintf(stderr, "%s %s: ", str[min(level - 1, 3)], base_name);
119  fprintf(stderr, "%s %s: ", str[((level - 1) <= (3) ? (level - 1) : (3))], base_name);
120 
121  vfprintf(stderr, fmt, ap);
122  fprintf(stderr, "\n");
123  }
124 }
125 
126 template<typename FP_TYPE_>
127 int Sox<FP_TYPE_>::openWrite(const string &fileName, double fs, int channels, double maxVal, unsigned int wordSize, bool switchEndian, int revBytes, int revNibbles, int revBits){
128  int retVal=NO_ERROR; // start assuming no error
129  bool inputFile=false;
130  close(inputFile);
131 
132  // setup the desired signalinfo
133  sox_signalinfo_t si; // the signal info.
134  si.rate=fs;
135  si.channels=channels;
136  si.precision=wordSize; // the precision is the number of bits of the data type
137  si.length=0;
138  si.mult=NULL;
139 
140  sox_encodinginfo_t encoding; // get default encodings
141  sox_init_encodinginfo(&encoding);
142  encoding.encoding=SOX_ENCODING_UNKNOWN; // setup the endcoding
143  encoding.bits_per_sample=wordSize;
144  encoding.opposite_endian=(switchEndian)?sox_true:sox_false;
145  encoding.reverse_bytes=(revBytes==0)?sox_option_no:((revBytes==1)?sox_option_yes:sox_option_default);
146  encoding.reverse_nibbles=(revNibbles==0)?sox_option_no:((revNibbles==1)?sox_option_yes:sox_option_default);
147  encoding.reverse_bits=(revBits==0)?sox_option_no:((revBits==1)?sox_option_yes:sox_option_default);
148 
149  // the output file
150  out=sox_open_write(fileName.c_str(), &si, &encoding, NULL, NULL, NULL);
151  if (out==NULL)
153 /* cout<<"out->encoding.encoding "<<out->encoding.encoding<<endl;
154  cout<<"out->encoding.bits_per_sample "<<out->encoding.bits_per_sample<<endl;
155  cout<<"out->encoding.compression "<<out->encoding.compression<<endl;
156  cout<<"out->encoding.reverse_bytes "<<out->encoding.reverse_bytes<<endl;
157  cout<<"out->encoding.reverse_nibbles "<<out->encoding.reverse_nibbles<<endl;
158  cout<<"out->encoding.reverse_bits "<<out->encoding.reverse_bits<<endl;
159  cout<<"out->encoding.opposite_endian "<<out->encoding.opposite_endian<<endl;
160 */
161  outputMaxVal=maxVal;
162  // write the maximum value to file
163  ofstream outf((fileName+".max").c_str());
164  outf.precision(20);
165  outf<< scientific << outputMaxVal;
166  outf.close();
167  return retVal;
168 }
169 
170 template<typename FP_TYPE_>
171 int Sox<FP_TYPE_>::openMemWrite(void *buffer, size_t len, double fs, int channels, double maxVal, unsigned int wordSize, bool switchEndian, int revBytes, int revNibbles, int revBits){
172  int retVal=NO_ERROR; // start assuming no error
173  bool inputFile=false;
174  close(inputFile);
175 
176  // setup the desired signalinfo
177  sox_signalinfo_t si; // the signal info.
178  si.rate=fs;
179  si.channels=channels;
180  si.precision=wordSize; // the precision is the number of bits of the data type
181  si.length=0;
182  si.mult=NULL;
183 
184  sox_encodinginfo_t encoding; // get default encodings
185  sox_init_encodinginfo(&encoding);
186  encoding.encoding=SOX_ENCODING_UNKNOWN; // setup the endcoding
187  encoding.bits_per_sample=wordSize;
188  encoding.opposite_endian=(switchEndian)?sox_true:sox_false;
189  encoding.reverse_bytes=(revBytes==0)?sox_option_no:((revBytes==1)?sox_option_yes:sox_option_default);
190  encoding.reverse_nibbles=(revNibbles==0)?sox_option_no:((revNibbles==1)?sox_option_yes:sox_option_default);
191  encoding.reverse_bits=(revBits==0)?sox_option_no:((revBits==1)?sox_option_yes:sox_option_default);
192 
193  // the output memory buffer
194  out=sox_open_mem_write(buffer, len, &si, &encoding, NULL, NULL);
195  if (out==NULL)
197  outputMaxVal=maxVal;
198  return retVal;
199 }
200 
201 
202 template<typename FP_TYPE_>
203 int Sox<FP_TYPE_>::write(const vector<vector<FP_TYPE_> > &audioData) {
204  int retVal=NO_ERROR; // start assuming no error
205  if (out) { // if the output file has been opened...
206  if (out->signal.channels!=audioData.size())
208  else {
209  int ch=out->signal.channels;
210  int len=audioData[0].size();
211  int total=ch*len;
212  if (outputBuffer.size()<total)
213  outputBuffer.resize(total);
214  for (int i=0; i<audioData.size(); i++) // stride the interleaved outputBuffer with each channel
215  for (int j=0; j<len; j++)
216  outputBuffer[j*ch+i]=(sox_sample_t)((double)audioData[i][j]/outputMaxVal*(double)numeric_limits<sox_sample_t>::max());
217  size_t writeCount=sox_write(out, &outputBuffer[0], total);
218  retVal=writeCount;
219  }
220  } else
222  return retVal;
223 }
224 
225 template<typename FP_TYPE_>
227  bool inputFile=true;
228  return close(inputFile);
229 }
230 
231 template<typename FP_TYPE_>
233  bool inputFile=false;
234  return close(inputFile);
235 }
236 
237 template<typename FP_TYPE_>
238 vector<string> Sox<FP_TYPE_>::availableFormats(void) {
239  size_t i;
240  char const * const * names;
241  vector<string> formatExts;
242 
243  sox_format_init();
244  for (i = 0; sox_format_fns[i].fn; ++i)
245  char const * const *names = sox_format_fns[i].fn()->names;
246 
247  printf("AUDIO FILE FORMATS:");
248  for (i = 0; sox_format_fns[i].fn; ++i) {
249  sox_format_handler_t const * handler = sox_format_fns[i].fn();
250  if (!(handler->flags & SOX_FILE_DEVICE))
251  for (names = handler->names; *names; ++names)
252  if (!strchr(*names, '/'))
253  formatExts.push_back(*names);
254  }
255  std::sort(formatExts.begin(), formatExts.end());
256  return formatExts;
257 }
258 
259 template<typename FP_TYPE_>
261  printf("The known output file extensions (output file formats) are the following :\n");
262  vector<string> formats=availableFormats();
263  for (int i=0; i<formats.size(); i++)
264  printf("%s ",formats[i].c_str());
265  printf("\n");
266 }
267 
268 #ifndef HAVE_EMSCRIPTEN
269 template class Sox<short int>;
270 template class Sox<int>;
271 template class Sox<float>;
272 #endif
273 template class Sox<double>;
274 
275 #ifdef HAVE_EMSCRIPTEN
276 
277 template<typename FP_TYPE_>
278 FP_TYPE_ Sox<FP_TYPE_>::getSample(unsigned int r, unsigned int c){
279  if (r>=Sox<FP_TYPE_>::audio.rows()) {
281  typedef std::numeric_limits<double> Info;
282  return Info::quiet_NaN();
283  }
284  if (c>=audio.cols()) {
286  typedef std::numeric_limits<double> Info;
287  return Info::quiet_NaN();
288  }
289  return audio(r,c);
290 }
291 
292 template<typename FP_TYPE_>
293 unsigned int Sox<FP_TYPE_>::getRows(){
294  return audio.rows();
295 }
296 
297 template<typename FP_TYPE_>
298 unsigned int Sox<FP_TYPE_>::getCols(){return Sox<FP_TYPE_>::audio.cols();}
299 
300 template<typename FP_TYPE_>
301 int Sox<FP_TYPE_>::readJS(unsigned int count){
302  return read(audio, count);
303 }
304 
305 #include <emscripten/bind.h>
306 EMSCRIPTEN_BINDINGS(Sox_ex) {
307  emscripten::class_<Sox<double>>("Sox")
308  .constructor()
309  .function("printFormats", &Sox<double>::printFormats)
310  .function("getSample", &Sox<double>::getSample)
311  .function("getRows", &Sox<double>::getRows)
312  .function("getCols", &Sox<double>::getCols)
313  .function("openRead", emscripten::select_overload<int(intptr_t, size_t)>(&Sox<double>::openRead), emscripten::allow_raw_pointers())
314  .function("read", &Sox<double>::readJS)
315  ;
316 }
317 #endif
#define SOX_READ_MAXSCALE_ERROR
Sox couldn&#39;t open the filename.max to read the rescale value for the audio file.
Definition: Sox.H:36
virtual int openWrite(const string &fileName, double fs, int channels, double maxVal)
Definition: Sox.H:174
int openRead(string fileName)
Definition: Sox.C:70
virtual int evaluateError(int errorNum)
Definition: Debug.H:132
#define SOX_COL_BOUNDS_ERROR
Error when trying to access a col out of bounds (Emscripten case)
Definition: Sox.H:42
int closeWrite(void)
Definition: Sox.C:232
int openMemWrite(void *buffer, size_t len, double fs, int channels, double maxVal)
Definition: Sox.H:202
vector< string > availableFormats(void)
Definition: Sox.C:238
#define SOX_ROW_BOUNDS_ERROR
Error when trying to access a row out of bounds (Emscripten case)
Definition: Sox.H:41
#define SOX_WRITE_FILE_OPEN_ERROR
Error when libsox couldn&#39;t open the output file.
Definition: Sox.H:37
#define NO_ERROR
There is no error.
Definition: Debug.H:33
#define SOX_READ_FILE_OPEN_ERROR
Error when libsox couldn&#39;t open the input file.
Definition: Sox.H:32
Definition: Sox.H:95
#define SOX_WRITE_FILE_NOT_OPENED_ERROR
Error when the output file hasn&#39;t already been opened using Sox::openRead.
Definition: Sox.H:38
Definition: Sox.H:54
static void output_message(unsigned level, const char *filename, const char *fmt, va_list ap)
Definition: Sox.C:113
void printFormats()
Definition: Sox.C:260
int closeRead(void)
Definition: Sox.C:226
#define SOX_CLOSE_FILE_ERROR
Error when libsox couldn&#39;t close the file.
Definition: Sox.H:33
int close(bool inputFile)
Definition: Sox.C:51
#define SOX_WRITE_OUT_CHANNEL_MISMATCH
Error when trying to write data and the channel count doesn&#39;t match.
Definition: Sox.H:39
Sox()
Constructor.
Definition: Sox.C:35
virtual ~Sox()
Destructor.
Definition: Sox.C:44
virtual int write(const vector< vector< FP_TYPE_ > > &audioData)
Definition: Sox.C:203
gtkIOStream: /tmp/gtkiostream/src/Sox.C Source File
GTK+ IOStream  Beta