Skip to content

Commit

Permalink
Added support for .wav files with IEEE float 32-bit samples
Browse files Browse the repository at this point in the history
  • Loading branch information
gtzan committed Oct 8, 2015
1 parent 72818ba commit 42aaf3c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 7 deletions.
78 changes: 72 additions & 6 deletions src/marsyas/marsystems/WavFileSource.cpp
Expand Up @@ -26,6 +26,7 @@ using namespace Marsyas;
WavFileSource::WavFileSource(mrs_string name):AbsSoundFileSource("WavFileSource",name)
{
idata_ = 0;
fdata_ = 0;
sdata_ = 0;
cdata_ = 0;
sldata_ = 0;
Expand All @@ -39,6 +40,7 @@ WavFileSource::WavFileSource(mrs_string name):AbsSoundFileSource("WavFileSource"
WavFileSource::WavFileSource(const WavFileSource& a): AbsSoundFileSource(a)
{
idata_ = 0;
fdata_ = 0;
sdata_ = 0;
cdata_ = 0;
sldata_ = 0;
Expand All @@ -62,6 +64,7 @@ WavFileSource::WavFileSource(const WavFileSource& a): AbsSoundFileSource(a)
WavFileSource::~WavFileSource()
{
delete [] idata_;
delete [] fdata_;
delete [] sdata_;
delete [] cdata_;
delete [] sldata_;
Expand Down Expand Up @@ -194,18 +197,18 @@ WavFileSource::getHeader(mrs_string filename)
//chunkSize = chunkSize;
#endif

unsigned short format_tag;
if (fread(&format_tag, 2, 1, sfp_) != 1) {

if (fread(&format_tag_, 2, 1, sfp_) != 1) {
MRSERR("Error reading wav file");
}

#if defined(MARSYAS_BIGENDIAN)
format_tag = ByteSwapShort(format_tag);
format_tag_ = ByteSwapShort(format_tag_);
#else
//format_tag = format_tag;
//format_tag_ = format_tag_;
#endif

if (format_tag != 1)
if ((format_tag_ != 1)&&(format_tag_ != 3))
{
fclose(sfp_);
MRSWARN("Non pcm(compressed) wave files are not supported");
Expand Down Expand Up @@ -354,11 +357,13 @@ WavFileSource::myUpdate(MarControlPtr sender)
rewindpos_ = getctrl("mrs_natural/loopPos")->to<mrs_natural>();

delete [] idata_;
delete [] fdata_;
delete [] sdata_;
delete [] cdata_;
delete [] sldata_;

idata_ = new int[inSamples_ * nChannels_];
fdata_ = new float[inSamples_ * nChannels_];
sdata_ = new short[inSamples_ * nChannels_];
cdata_ = new unsigned char[inSamples_ * nChannels_];
sldata_ = new myUint24_t[inSamples_ * nChannels_];

This comment has been minimized.

Copy link
@jleben

jleben Oct 8, 2015

Contributor

This is obviously a waste of memory. Why not allocating only what's needed?

This comment has been minimized.

Copy link
@gtzan

gtzan via email Oct 8, 2015

Author Member

This comment has been minimized.

Copy link
@gperciva

gperciva Oct 8, 2015

Member

I think the idea is that you only need 1 of idata, fdata, sdata, or cdata; the rest can be set to NULL.

This comment has been minimized.

Copy link
@jleben

jleben Oct 8, 2015

Contributor

Exactly. Also, idata, fdata, sdata and cdata could be packed into a union, so there wouldn't event be individual pointers.

This comment has been minimized.

Copy link
@gtzan

gtzan Oct 8, 2015

Author Member

As you don't know what type of .wav file it will be at construction time you would have to do the memory allocation after reading the header and not in the constructor. In general doing memory allocation only in the construction makes things cleaner and simpler. Doing a union is fine but also could make figuring out what's wrong if one of the cases goes wrong harder. Anyway I don't think it is a big deal so I am not going to bother but if you want to go ahead and stream line it I won't object.

This comment has been minimized.

Copy link
@jleben

jleben Oct 8, 2015

Contributor

As it is, the allocation is done in WavFileSource::myUpdate, not at construction. And SoundFileSource also calls getHeader() in its myUpdate. So I don't see a problem in allocating based on the header.

This comment has been minimized.

Copy link
@gtzan

gtzan Oct 8, 2015

Author Member

I should have checked the code before opening my mouth :-). Feel free to go ahead and do the header base allocation I might get to it tomorrow.

This comment has been minimized.

Copy link
@jleben

jleben Oct 8, 2015

Contributor

I have just implemented a proof-of-concept libsndfile based sound source. Only 150 lines of code. With your permission, George, I will include libsndfile in Marsyas sources and integrate the new sound file source into the existing system (automatic selection in SoundFileSource, etc...)

This comment has been minimized.

Copy link
@gtzan

gtzan Oct 8, 2015

Author Member

You are the man - just make sure that it can be turned on/off with CMake just to avoid full dependence on it.

Expand Down Expand Up @@ -420,7 +425,65 @@ WavFileSource::getLinear8(realvec& slice)


mrs_natural
WavFileSource::getFloat32(realvec& slice)
{
mrs_natural c,t;

fseek(sfp_, 4 * pos_ * nChannels_ + sfp_begin_, SEEK_SET);
samplesRead_ = (mrs_natural)fread(fdata_, sizeof(float), samplesToRead_, sfp_);

// pad with zeros if necessary
if ((samplesRead_ != samplesToRead_)&&(samplesRead_ != 0))
{
for (c=0; c < nChannels_; ++c)
for (t=0; t < inSamples_; t++)
slice(c, t) = 0.0;
samplesToWrite_ = samplesRead_ / nChannels_;
}
else // default case - read enough samples or no samples in which case zero output
{
samplesToWrite_ = inSamples_;

// if there are no more samples output zeros
if (samplesRead_ == 0)
for (t=0; t < inSamples_; t++)
{
nt_ = nChannels_ * t;
for (c=0; c < nChannels_; ++c)
{
fdata_[nt_ + c] = 0;
}
}
}

// write the read samples to output slice once for each channel
for (t=0; t < samplesToWrite_; t++)
{
ival_ = 0;
nt_ = nChannels_ * t;
#if defined(MARSYAS_BIGENDIAN)
for (c=0; c < nChannels_; ++c)
{
fval_ = fdata_[nt_ + c];
slice(c, t) = (mrs_real) fval_;
}
#else
for (c=0; c < nChannels_; ++c)
{
fval_ = fdata_[nt_ + c];
slice(c, t) = (mrs_real) fval_;
}
#endif
}

pos_ += samplesToWrite_;
return pos_;
}




mrs_natural
WavFileSource::getLinear32(realvec& slice)
{
mrs_natural c,t;
Expand Down Expand Up @@ -604,7 +667,10 @@ WavFileSource::myProcess(realvec& in, realvec& out)
{
case 32:
{
getLinear32(out);
if (format_tag_ == 1)
getLinear32(out);
else
getFloat32(out);
ctrl_pos_->setValue(pos_, NOUPDATE);

if (pos_ >= rewindpos_ + csize_)
Expand Down
5 changes: 4 additions & 1 deletion src/marsyas/marsystems/WavFileSource.h
Expand Up @@ -44,6 +44,7 @@ class WavFileSource: public AbsSoundFileSource
{
private:
int *idata_;
float *fdata_;
short *sdata_;
unsigned char *cdata_;
myUint24_t *sldata_;
Expand All @@ -55,6 +56,7 @@ class WavFileSource: public AbsSoundFileSource
mrs_natural csize_;
mrs_natural size_;
int ival_;
float fval_;
short sval_;
unsigned short bits_;
MarControlPtr ctrl_pos_;
Expand Down Expand Up @@ -82,7 +84,8 @@ class WavFileSource: public AbsSoundFileSource
mrs_natural getLinear24(realvec& win);
mrs_natural getLinear16(realvec& win);
mrs_natural getLinear8(realvec& win);

mrs_natural getFloat32(realvec& win);
unsigned short format_tag_;

public:
WavFileSource(std::string name);
Expand Down

0 comments on commit 42aaf3c

Please sign in to comment.