⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 legacyblockfile.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
字号:
/**********************************************************************  Audacity: A Digital Audio Editor  LegacyBlockFile.cpp  Dominic Mazzoni  Audacity 1.1.0 block file format:  1. Header tag: 20 bytes     "AudacityBlockFile110"  2. 64K summaries (min, max, RMS, each a 4-byte float)  3. 256 summaries (min, max, RMS, each a 4-byte float)**********************************************************************/#include <float.h>#include <math.h>#include <wx/filefn.h>#include <wx/ffile.h>#include <wx/utils.h>#include <wx/log.h>#include "LegacyBlockFile.h"#include "../FileFormats.h"#include "../Internat.h"#include "sndfile.h"void ComputeLegacySummaryInfo(wxFileName fileName,                              int summaryLen,                              sampleFormat format,                              SummaryInfo *info,                              bool noRMS,bool Silent,                              float *min, float *max, float *rms){   int fields = 3; /* min, max, rms */   if (noRMS)      fields = 2;   info->fields = fields;   info->format = format;   info->bytesPerFrame =      SAMPLE_SIZE(info->format) * fields;   info->totalSummaryBytes = summaryLen;   info->offset64K = 20; /* legacy header tag len */   info->frames64K = (summaryLen-20) /      (info->bytesPerFrame * 256);   info->offset256 = info->offset64K +      (info->frames64K * info->bytesPerFrame);   info->frames256 =      (summaryLen - 20 -       (info->frames64K * info->bytesPerFrame)) /      info->bytesPerFrame;   //   // Compute the min, max, and RMS of the block from the   // 64K summary data   //   float *summary = new float[info->frames64K * fields];   samplePtr data = NewSamples(info->frames64K * fields,                               info->format);   wxLogNull *silence=0;   wxFFile summaryFile(fileName.GetFullPath().c_str(), wxT("rb"));   int read;   if(Silent)silence= new wxLogNull();   if( !summaryFile.IsOpened() ) {      wxLogWarning(wxT("Unable to access summary file %s; substituting silence for remainder of session"),                   fileName.GetFullPath().c_str());      read=info->frames64K * info->bytesPerFrame;      memset(data,0,read);   }else{      summaryFile.Seek(info->offset64K);      read = summaryFile.Read(data,                              info->frames64K *                              info->bytesPerFrame);   }   if(silence) delete silence;   int count = read / info->bytesPerFrame;   CopySamples(data, info->format,               (samplePtr)summary, floatSample, count);   (*min) = FLT_MAX;   (*max) = FLT_MIN;   float sumsq = 0;   for(int i=0; i<count; i++) {      if (summary[fields*i] < (*min))         (*min) = summary[fields*i];      if (summary[fields*i+1] > (*max))         (*max) = summary[fields*i+1];      if (fields >= 3)         sumsq += summary[fields*i+2]*summary[fields*i+2];   }   if (fields >= 3)      (*rms) = sqrt(sumsq / count);   else      (*rms) = 0;   DeleteSamples(data);   delete[] summary;   }/// Construct a LegacyBlockFile memory structure that will point to an/// existing block file.  This file must exist and be a valid block file.////// @param existingFile The disk file this LegacyBlockFile should use.LegacyBlockFile::LegacyBlockFile(wxFileName existingFile,                                 sampleFormat format,                                 sampleCount summaryLen,                                 sampleCount len,                                 bool noRMS):   BlockFile(existingFile, len),   mFormat(format){   sampleFormat summaryFormat;   if (noRMS)      summaryFormat = int16Sample;   else      summaryFormat = floatSample;   ComputeLegacySummaryInfo(existingFile,                            summaryLen, summaryFormat,                            &mSummaryInfo, noRMS, FALSE,                            &mMin, &mMax, &mRMS);}LegacyBlockFile::~LegacyBlockFile(){}/// Read the summary section of the disk file.////// @param *data The buffer to write the data to.  It must be at least/// mSummaryinfo.totalSummaryBytes long.bool LegacyBlockFile::ReadSummary(void *data){   wxFFile summaryFile(mFileName.GetFullPath().c_str(), wxT("rb"));   wxLogNull *silence=0;   if(mSilentLog)silence= new wxLogNull();   if( !summaryFile.IsOpened() ){      memset(data,0,(size_t)mSummaryInfo.totalSummaryBytes);      if(silence) delete silence;      mSilentLog=TRUE;      return true;   }   int read = summaryFile.Read(data, (size_t)mSummaryInfo.totalSummaryBytes);      if(silence) delete silence;   mSilentLog=FALSE;   return (read == mSummaryInfo.totalSummaryBytes);}/// Read the data portion of the block file using libsndfile.  Convert it/// to the given format if it is not already.////// @param data   The buffer where the data will be stored/// @param format The format the data will be stored in/// @param start  The offset in this block file/// @param len    The number of samples to readint LegacyBlockFile::ReadData(samplePtr data, sampleFormat format,                              sampleCount start, sampleCount len){   SF_INFO info;   memset(&info, 0, sizeof(info));   switch(mFormat) {   case int16Sample:      info.format =         SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU;      break;   default:   case floatSample:      info.format =         SF_FORMAT_RAW | SF_FORMAT_FLOAT | SF_ENDIAN_CPU;      break;   case int24Sample:      info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32 | SF_ENDIAN_CPU;      break;   }   info.samplerate = 44100; // Doesn't matter   info.channels = 1;   info.frames = mLen + (mSummaryInfo.totalSummaryBytes /                         SAMPLE_SIZE(mFormat));      #ifdef _UNICODE      /* sf_open doesn't handle fn_Str() in Unicode build. May or may not actually work. */      SNDFILE *sf=sf_open(FILENAME(mFileName.GetFullPath()).mb_str(), SFM_READ, &info);   #else // ANSI      SNDFILE *sf=sf_open(FILENAME(mFileName.GetFullPath()).fn_str(), SFM_READ, &info);   #endif // Unicode/ANSI   wxLogNull *silence=0;   if(mSilentLog)silence= new wxLogNull();   if (!sf){             memset(data,0,SAMPLE_SIZE(format)*len);      if(silence) delete silence;      mSilentLog=TRUE;      return len;   }   if(silence) delete silence;   mSilentLog=FALSE;   sf_count_t seekstart = start +         (mSummaryInfo.totalSummaryBytes / SAMPLE_SIZE(mFormat));   sf_seek(sf, seekstart , SEEK_SET);      samplePtr buffer = NewSamples(len, floatSample);   int framesRead = 0;      // If both the src and dest formats are integer formats,   // read integers from the file (otherwise we would be   // converting to float and back, which is unneccesary)   if (format == int16Sample &&       sf_subtype_is_integer(info.format)) {      framesRead = sf_readf_short(sf, (short *)data, len);   }else if (format == int24Sample &&             sf_subtype_is_integer(info.format)) {      framesRead = sf_readf_int(sf, (int *)data, len);               // libsndfile gave us the 3 byte sample in the 3 most      // significant bytes -- we want it in the 3 least      // significant bytes.      int *intPtr = (int *)data;      for( int i = 0; i < framesRead; i++ )         intPtr[i] = intPtr[i] >> 8;   } 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);      CopySamples(buffer, floatSample,                  (samplePtr)data, format, framesRead);   }      sf_close(sf);      DeleteSamples(buffer);   return framesRead;}void LegacyBlockFile::SaveXML(int depth, wxFFile &xmlFile){   for(int i = 0; i < depth; i++)      xmlFile.Write(wxT("\t"));   xmlFile.Write(wxT("<legacyblockfile "));   xmlFile.Write(wxString::Format(wxT("name='%s' "),                                  XMLTagHandler::XMLEsc(mFileName.GetFullName()).c_str()));   xmlFile.Write(wxString::Format(wxT("len='%d' "), mLen));   if (mSummaryInfo.fields < 3)      xmlFile.Write(wxString::Format(wxT("norms='1' ")));   xmlFile.Write(wxString::Format(wxT("summarylen='%d' "), mSummaryInfo.totalSummaryBytes));   xmlFile.Write(wxT("/>\n"));}/// staticBlockFile *LegacyBlockFile::BuildFromXML(wxString projDir, const wxChar **attrs,                                         sampleCount len, sampleFormat format){   wxFileName fileName;   sampleCount summaryLen = 0;   bool noRMS = false;   while(*attrs)   {       const wxChar *attr =  *attrs++;       const wxChar *value = *attrs++;       if( !wxStrcmp(attr, wxT("name")) )          fileName.Assign(projDir, value);       if( !wxStrcmp(attr, wxT("len")) )          len = wxAtoi(value);       if( !wxStrcmp(attr, wxT("norms")) )          noRMS = wxAtoi(value)?true:false;       if( !wxStrcmp(attr, wxT("format")) )          format = (sampleFormat)wxAtoi(value);       if( !wxStrcmp(attr, wxT("summarylen")) )          summaryLen = wxAtoi(value);   }   return new LegacyBlockFile(fileName, format, summaryLen, len, noRMS);}/// Create a copy of this BlockFile, but using a different disk file.////// @param newFileName The name of the new file to use.BlockFile *LegacyBlockFile::Copy(wxFileName newFileName){   BlockFile *newBlockFile = new LegacyBlockFile(newFileName,                                                 mFormat,                                                 mSummaryInfo.totalSummaryBytes,                                                 mLen,                                                 mSummaryInfo.fields < 3);   return newBlockFile;}int LegacyBlockFile::GetSpaceUsage(){   wxFFile dataFile(mFileName.GetFullPath());   return dataFile.Length();}void LegacyBlockFile::Recover(){}// Indentation settings for Vim and Emacs and unique identifier for Arch, a// version control system. Please do not modify past this point.//// Local Variables:// c-basic-offset: 3// indent-tabs-mode: nil// End://// vim: et sts=3 sw=3// arch-tag: e84a3cdf-2140-43b4-98fa-ca8b22ec1df8

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -