File: soundFile.cpp

package info (click to toggle)
pyepl 1.1.0-3.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,120 kB
  • sloc: cpp: 7,986; python: 6,026; makefile: 360; ansic: 132
file content (254 lines) | stat: -rw-r--r-- 5,353 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// PyEPL: hardware/sound/soundFile.cpp
//
// Copyright (C) 2003-2005 Michael J. Kahana
// Authors: Ian Schleifer, Per Sederberg, Aaron Geller, Josh Jacobs
// URL: http://memory.psych.upenn.edu/programming/pyepl
//
// Distributed under the terms of the GNU Lesser General Public License
// (LGPL). See the license.txt that came with this file.
// soundFile class
//


#include "soundFile.h"

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;


soundFile::soundFile(const char *filename, int mode, int format, int channels, int samplerate)
{
  file = NULL;

  // call the open method
  open(filename,mode,format,channels,samplerate);
  
}


soundFile::~soundFile()
{
  close();
}


int soundFile::open(const char *filename, int mode, int format, int channels, int samplerate)
{
  // see if should use provided info
  if (format != 0 )
  {
    info.format = format;
  }
  if (channels != 0)
  {
    info.channels = channels;
  }
  if (samplerate != 0)
  {
    info.samplerate = samplerate;
  }

  // open the file filling the info
  file = sf_open(filename, mode, &info);
  if (file == NULL)
  {
    cerr << "ERROR: sf_open failed." << endl;
    cerr << sf_strerror(file) << endl;
    return -1;
  }

  return 0;
}


int soundFile::close()
{
  // close the sndfile if it exists
  if (file)
  {
    return sf_close(file);
  }
  return 0;
}

long soundFile::getTotalSamples()
{
  return (long)(info.channels * info.frames);
}

int soundFile::getChannels()
{
  return info.channels;
}

int soundFile::getSamplerate()
{
  return info.samplerate;
}

int soundFile::getFormat()
{
  return info.format;
}

long soundFile::getFrames()
{
  return info.frames;
}


float *soundFile::readfile_float(int resampledrate)
{
  long toread = info.channels*info.frames;
  long numread;

  // allocate the space for the data
  float *data = new float[toread];

  // read in the data from the entire file
  numread = sf_readf_float(file,data,info.frames);
  if (numread != info.frames)
  {
    // Did not read in all that was expected
    cerr << "WARNING: sf_read only read " << numread << " out of " << info.frames << " frames." << endl;
    info.frames = numread;
  }

  // see if resample
  if (resampledrate > 0 && resampledrate != info.samplerate)
  {
    // resample the data to the new rate
    float *newdata = NULL;
    newdata = resample(data,(double)resampledrate/info.samplerate);
    
    // move the data around and delete the old data
    float *tempdata = data;
    data = newdata;
    newdata = tempdata;
    delete newdata;

    // set the new samplerate
    info.samplerate = resampledrate;
  }
  
  return data;
}

short *soundFile::readfile_short(int resampledrate)
{
  long toread;
  long numread;
  short *shortdata;

  // see if resample
  if (resampledrate > 0 && resampledrate != info.samplerate)
  {
    // we will resample, so should read in floats
    // get the data
    float *floatdata = NULL;
    floatdata = readfile_float(resampledrate);

    // convert the data to a float
    toread = info.channels*info.frames;
    shortdata = new short[toread];
  
    long i;
    for (i=0; i<toread; i++)
    {
      shortdata[i] = static_cast<short>(floatdata[i] * SHORT_RANGE);
    }

    // delete the float data
    delete floatdata;
  }
  else
  {
    // can just read short data
    toread = info.channels*info.frames;
    shortdata = new short[toread];

    // read in shorts from the entire file
    numread = sf_readf_short(file,shortdata,info.frames);
    if (numread != info.frames)
    {
      // Did not read in all that was expected
      cerr << "WARNING: sf_read only read " << numread << " out of " << info.frames << " frames." << endl;
      info.frames = numread;
    }
  }

  // return the short data
  return shortdata;
}

int soundFile::append_float(float *data, long numSamples)
{
  long ret;

  // File must be open

  // seek to the end
  ret = sf_seek(file, 0, SEEK_END);

  // append the float data
  ret = sf_write_float(file, data, numSamples);
  if (ret != numSamples)
  {
    // Did not write everything for some reason
    cerr << "WARNING: sf_write only appended " << ret << " out of " << numSamples << " samples." << endl;
  }
  return 0;
}

int soundFile::append_short(short *data, long numSamples)
{

  long ret;

  // File must be open

  // seek to the end
  ret = sf_seek(file, 0, SEEK_END);

  // append the float data
  ret = sf_write_short(file, data, numSamples);
  if (ret != numSamples)
  {
    // Did not write everything for some reason
    cerr << "WARNING: sf_write only appended " << ret << " out of " << numSamples << " samples." << endl;
  }
  return 0;
}


float *soundFile::resample(float *indata, double ratio)
{
  SRC_DATA sdata;

  // allocate space for new data
  long newsize = (long)(info.channels * ratio * info.frames);
  float *outdata = new float[newsize];
  
  // set up the struct
  sdata.data_in = indata;
  sdata.data_out = outdata;
  sdata.input_frames = info.frames;
  sdata.output_frames = (long)newsize/info.channels;
  sdata.src_ratio = ratio;

  int res = src_simple(&sdata, SRC_SINC_FASTEST, info.channels);

  if (res != 0)
  {
    cerr << "ERROR: Resampling failed." << endl;
    cerr << src_strerror(res) << endl;
    return NULL;
  }

  // update the frames to be the new number of samples
  info.frames = sdata.output_frames_gen;

  return outdata;
}