/********************************************************************** Audacity: A Digital Audio Editor PCMAliasBlockFile.cpp Joshua Haberman **********************************************************************/ #include #include #include #include "PCMAliasBlockFile.h" #include "../FileFormats.h" #include "../Internat.h" PCMAliasBlockFile::PCMAliasBlockFile(wxFileName fileName, wxFileName aliasedFile, sampleCount aliasStart, sampleCount aliasLen, int aliasChannel): AliasBlockFile(fileName, aliasedFile, aliasStart, aliasLen, aliasChannel) { AliasBlockFile::WriteSummary(); } PCMAliasBlockFile::PCMAliasBlockFile(wxFileName existingFileName, wxFileName aliasedFile, sampleCount aliasStart, sampleCount aliasLen, int aliasChannel, float min, float max, float rms): AliasBlockFile(existingFileName, aliasedFile, aliasStart, aliasLen, aliasChannel, min, max, rms) { } PCMAliasBlockFile::~PCMAliasBlockFile() { } /// Reads the specified data from the aliased file, using libsndfile, /// and converts it to the given sample format. /// /// @param data The buffer to read the sample data into. /// @param format The format to convert the data into /// @param start The offset within the block to begin reading /// @param len The number of samples to read int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format, sampleCount start, sampleCount len) { SF_INFO info; memset(&info, 0, sizeof(info)); SNDFILE *sf = sf_open(FILENAME(mAliasedFileName.GetFullPath()), SFM_READ, &info); if (!sf) return 0; sf_seek(sf, mAliasStart + start, SEEK_SET); samplePtr buffer = NewSamples(len * info.channels, floatSample); int framesRead = 0; if (format == int16Sample && !sf_subtype_more_than_16_bits(info.format)) { // Special case: if the file is in 16-bit (or less) format, // and the calling method wants 16-bit data, go ahead and // read 16-bit data directly. This is a pretty common // case, as most audio files are 16-bit. framesRead = sf_readf_short(sf, (short *)buffer, len); for (int i = 0; i < framesRead; i++) ((short *)data)[i] = ((short *)buffer)[(info.channels * i) + mAliasChannel]; } else { // Otherwise, let libsndfile handle the conversion and // scaling, and pass us normalized data as floats. We can // then convert to whatever format we want. framesRead = sf_readf_float(sf, (float *)buffer, len); float *bufferPtr = &((float *)buffer)[mAliasChannel]; CopySamples((samplePtr)bufferPtr, floatSample, (samplePtr)data, format, framesRead, true, info.channels); } DeleteSamples(buffer); sf_close(sf); return framesRead; } /// Construct a new PCMAliasBlockFile based on this one, but writing /// the summary data to a new file. /// /// @param newFileName The filename to copy the summary data to. BlockFile *PCMAliasBlockFile::Copy(wxFileName newFileName) { BlockFile *newBlockFile = new PCMAliasBlockFile(newFileName, mAliasedFileName, mAliasStart, mLen, mAliasChannel, mMin, mMax, mRMS); return newBlockFile; } void PCMAliasBlockFile::SaveXML(int depth, wxFFile &xmlFile) { for(int i = 0; i < depth; i++) xmlFile.Write("\t"); xmlFile.Write("\n"); } BlockFile *PCMAliasBlockFile::BuildFromXML(wxString projDir, const char **attrs) { wxFileName summaryFileName; wxFileName aliasFileName; int aliasStart=0, aliasLen=0, aliasChannel=0; float min=0, max=0, rms=0; while(*attrs) { const char *attr = *attrs++; const char *value = *attrs++; if( !wxStricmp(attr, "summaryfile") ) summaryFileName.Assign(projDir, value); if( !wxStricmp(attr, "aliasfile") ) aliasFileName.Assign(value); if( !wxStricmp(attr, "aliasstart") ) aliasStart = atoi(value); if( !wxStricmp(attr, "aliaslen") ) aliasLen = atoi(value); if( !wxStricmp(attr, "aliaschannel") ) aliasChannel = atoi(value); if( !wxStricmp(attr, "min") ) min = atoi(value); if( !wxStricmp(attr, "max") ) max = atoi(value); if( !wxStricmp(attr, "rms") ) rms = atoi(value); } return new PCMAliasBlockFile(summaryFileName, aliasFileName, aliasStart, aliasLen, aliasChannel, min, max, rms); }