示例#1
0
/// Write the summary to disk, using the derived ReadData() to get the data
void ODPCMAliasBlockFile::WriteSummary()
{
   // To build the summary data, call ReadData (implemented by the
   // derived classes) to get the sample data
   // Call this first, so that in case of exceptions from ReadData, there is
   // no NEW output file
   SampleBuffer sampleData(mLen, floatSample);
   this->ReadData(sampleData.ptr(), floatSample, 0, mLen, true);

   ArrayOf< char > fileNameChar;
   FILE *summaryFile{};
   {
      //the mFileName path may change, for example, when the project is saved.
      //(it moves from /tmp/ to wherever it is saved to.
      ODLocker locker { &mFileNameMutex };

      //wxFFile is not thread-safe - if any error occurs in opening the file,
      // it posts a wxlog message which WILL crash
      // Audacity because it goes into the wx GUI.
      // For this reason I left the wxFFile method commented out. (mchinen)
      //    wxFFile summaryFile(mFileName.GetFullPath(), wxT("wb"));

      // ...and we use fopen instead.
      wxString sFullPath = mFileName.GetFullPath();
      fileNameChar.reinit( strlen(sFullPath.mb_str(wxConvFile)) + 1 );
      strcpy(fileNameChar.get(), sFullPath.mb_str(wxConvFile));
      summaryFile = fopen(fileNameChar.get(), "wb");
   }

   // JKC ANSWER-ME: Whay is IsOpened() commented out?
   if (!summaryFile){//.IsOpened() ){

      // Never silence the Log w.r.t write errors; they always count
      //however, this is going to be called from a non-main thread,
      //and wxLog calls are not thread safe.
      wxPrintf("Unable to write summary data to file: %s", fileNameChar.get());

      throw FileException{
         FileException::Cause::Read, wxFileName{ fileNameChar.get() } };
   }

   ArrayOf<char> cleanup;
   void *summaryData = CalcSummary(sampleData.ptr(), mLen,
                                            floatSample, cleanup);

   //summaryFile.Write(summaryData, mSummaryInfo.totalSummaryBytes);
   fwrite(summaryData, 1, mSummaryInfo.totalSummaryBytes, summaryFile);
   fclose(summaryFile);


    //     wxPrintf("write successful. filename: %s\n", fileNameChar);

   mSummaryAvailableMutex.Lock();
   mSummaryAvailable=true;
   mSummaryAvailableMutex.Unlock();
}
/// Write the summary to disk, using the derived ReadData() to get the data
void ODPCMAliasBlockFile::WriteSummary()
{
    //the mFileName path may change, for example, when the project is saved.
    //(it moves from /tmp/ to wherever it is saved to.
    mFileNameMutex.Lock();

    //wxFFile is not thread-safe - if any error occurs in opening the file,
    // it posts a wxlog message which WILL crash
    // Audacity because it goes into the wx GUI.
    // For this reason I left the wxFFile method commented out. (mchinen)
    //    wxFFile summaryFile(mFileName.GetFullPath(), wxT("wb"));

    // ...and we use fopen instead.
    wxString sFullPath = mFileName.GetFullPath();
    char* fileNameChar = new char[strlen(sFullPath.mb_str(wxConvFile)) + 1];
    strcpy(fileNameChar, sFullPath.mb_str(wxConvFile));
    FILE* summaryFile = fopen(fileNameChar, "wb");

    mFileNameMutex.Unlock();

    if( !summaryFile) { //.IsOpened() ){

        // Never silence the Log w.r.t write errors; they always count
        //however, this is going to be called from a non-main thread,
        //and wxLog calls are not thread safe.
        printf("Unable to write summary data to file: %s", fileNameChar);
        delete [] fileNameChar;
        return;
    }
    delete [] fileNameChar;

    // To build the summary data, call ReadData (implemented by the
    // derived classes) to get the sample data
    samplePtr sampleData = NewSamples(mLen, floatSample);
    this->ReadData(sampleData, floatSample, 0, mLen);

    void *summaryData = CalcSummary(sampleData, mLen,
                                    floatSample);

    //summaryFile.Write(summaryData, mSummaryInfo.totalSummaryBytes);
    fwrite(summaryData, 1, mSummaryInfo.totalSummaryBytes, summaryFile);
    fclose(summaryFile);
    DeleteSamples(sampleData);
    delete [] (char *) summaryData;


    //     printf("write successful. filename: %s\n", fileNameChar);

    mSummaryAvailableMutex.Lock();
    mSummaryAvailable=true;
    mSummaryAvailableMutex.Unlock();
}
/// Write the summary to disk, using the derived ReadData() to get the data
void ODPCMAliasBlockFile::WriteSummary()
{
   
   //Below from BlockFile.cpp's method.  We need to delete the data returned by
   //CalcSummary, because it uses local info.  In the future we might do something
   //smarter and thread-dependant like a static thread context.
   wxFFile summaryFile(mFileName.GetFullPath(), wxT("wb"));

   if( !summaryFile.IsOpened() ){
      // Never silence the Log w.r.t write errors; they always count
      // as new errors
      
      //however, this is going to be called from a non-main thread,
      //and wxLog calls are not thread safe.
      printf("Unable to write summary data to file %s",
                   mFileName.GetFullPath().c_str());
      // If we can't write, there's nothing to do.
      return;
   }

   // To build the summary data, call ReadData (implemented by the
   // derived classes) to get the sample data
   samplePtr sampleData = NewSamples(mLen, floatSample);
   this->ReadData(sampleData, floatSample, 0, mLen);

   void *summaryData = CalcSummary(sampleData, mLen,
                                            floatSample);
   summaryFile.Write(summaryData, mSummaryInfo.totalSummaryBytes);

   DeleteSamples(sampleData);
   delete [] summaryData;
   
   
   //above from BlockFiles.cpps method
   
   

   mSummaryAvailableMutex.Lock();
   mSummaryAvailable=true;
   mSummaryAvailableMutex.Unlock();
}
示例#4
0
/// Write the summary to disk, using the derived ReadData() to get the data
/// Here, the decoder ODTask associated with this file must fetch the samples with
/// the ODDecodeTask::Decode() method.
void ODDecodeBlockFile::WriteODDecodeBlockFile()
{

    // To build the summary data, call ReadData (implemented by the
    // derived classes) to get the sample data
    samplePtr sampleData = NewSamples(mLen, floatSample);

    //use the decoder here.
    mDecoderMutex.Lock();

    if(!mDecoder)
    {
        mDecoderMutex.Unlock();
        return;
    }
    mDecoder->Decode(sampleData, mFormat, mDecodeFileStart, mLen);

    mDecoderMutex.Unlock();
    this->ReadData(sampleData, floatSample, 0, mLen);

    void *summaryData = CalcSummary(sampleData, mLen, floatSample);
    //OD TODO: use new write()
//   summaryFile.Write(summaryData, mSummaryInfo.totalSummaryBytes);
    WriteSimpleBlockFile(
        sampleData,
        mLen,
        mFormat,
        summaryData);

    DeleteSamples(sampleData);
    delete [] (char *) summaryData;


    mDataAvailableMutex.Lock();
    mDataAvailable=true;
    mDataAvailableMutex.Unlock();
}
示例#5
0
bool SimpleBlockFile::WriteSimpleBlockFile(
    samplePtr sampleData,
    sampleCount sampleLen,
    sampleFormat format,
    void* summaryData)
{
   wxFFile file(mFileName.GetFullPath(), wxT("wb"));
   if( !file.IsOpened() ){
      // Can't do anything else.
      return false;
   }

   auHeader header;

   // AU files can be either big or little endian.  Which it is is
   // determined implicitly by the byte-order of the magic 0x2e736e64
   // (.snd).  We want it to be native-endian, so we write the magic
   // to memory and then let it write that to a file in native
   // endianness
   header.magic = 0x2e736e64;

   // We store the summary data at the end of the header, so the data
   // offset is the length of the summary data plus the length of the header
   header.dataOffset = sizeof(auHeader) + mSummaryInfo.totalSummaryBytes;

   // dataSize is optional, and we opt out
   header.dataSize = 0xffffffff;

   switch(format) {
      case int16Sample:
         header.encoding = AU_SAMPLE_FORMAT_16;
         break;

      case int24Sample:
         header.encoding = AU_SAMPLE_FORMAT_24;
         break;

      case floatSample:
         header.encoding = AU_SAMPLE_FORMAT_FLOAT;
         break;
   }

   // TODO: don't fabricate
   header.sampleRate = 44100;

   // BlockFiles are always mono
   header.channels = 1;

   // Write the file
   ArrayOf<char> cleanup;
   if (!summaryData)
      summaryData = /*BlockFile::*/CalcSummary(sampleData, sampleLen, format, cleanup);
      //mchinen:allowing virtual override of calc summary for ODDecodeBlockFile.
      // PRL: cleanup fixes a possible memory leak!

   size_t nBytesToWrite = sizeof(header);
   size_t nBytesWritten = file.Write(&header, nBytesToWrite);
   if (nBytesWritten != nBytesToWrite)
   {
      wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
      return false;
   }

   nBytesToWrite = mSummaryInfo.totalSummaryBytes;
   nBytesWritten = file.Write(summaryData, nBytesToWrite);
   if (nBytesWritten != nBytesToWrite)
   {
      wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
      return false;
   }

   if( format == int24Sample )
   {
      // we can't write the buffer directly to disk, because 24-bit samples
      // on disk need to be packed, not padded to 32 bits like they are in
      // memory
      int *int24sampleData = (int*)sampleData;

      for( int i = 0; i < sampleLen; i++ )
      {
         nBytesToWrite = 3;
         nBytesWritten =
            #if wxBYTE_ORDER == wxBIG_ENDIAN
               file.Write((char*)&int24sampleData[i] + 1, nBytesToWrite);
            #else
               file.Write((char*)&int24sampleData[i], nBytesToWrite);
            #endif
         if (nBytesWritten != nBytesToWrite)
         {
            wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
            return false;
         }
      }
   }
   else
   {
      // for all other sample formats we can write straight from the buffer
      // to disk
      nBytesToWrite = sampleLen * SAMPLE_SIZE(format);
      nBytesWritten = file.Write(sampleData, nBytesToWrite);
      if (nBytesWritten != nBytesToWrite)
      {
         wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
         return false;
      }
   }

    return true;
}
示例#6
0
bool SimpleBlockFile::WriteSimpleBlockFile(
    samplePtr sampleData,
    sampleCount sampleLen,
    sampleFormat format,
    void* summaryData)
{
   // Now checked in the DirManager
   //wxASSERT( !wxFileExists(FILENAME(mFileName.GetFullPath())) );
   
   DEBUG_OUTPUT("Writing simple block file");

   // Open and write the file
   wxFFile file(mFileName.GetFullPath(), wxT("wb"));

   if( !file.IsOpened() ){
      // Can't do anything else.
      return false;
   }

   auHeader header;

   // AU files can be either big or little endian.  Which it is is
   // determined implicitly by the byte-order of the magic 0x2e736e64
   // (.snd).  We want it to be native-endian, so we write the magic
   // to memory and then let it write that to a file in native
   // endianness
   header.magic = 0x2e736e64;

   // We store the summary data at the end of the header, so the data
   // offset is the length of the summary data plus the length of the header
   header.dataOffset = sizeof(auHeader) + mSummaryInfo.totalSummaryBytes;

   // dataSize is optional, and we opt out
   header.dataSize = 0xffffffff;

   switch(format) {
      case int16Sample:
         header.encoding = AU_SAMPLE_FORMAT_16;
         break;

      case int24Sample:
         header.encoding = AU_SAMPLE_FORMAT_24;
         break;

      case floatSample:
         header.encoding = AU_SAMPLE_FORMAT_FLOAT;
         break;
   }

   // TODO: don't fabricate
   header.sampleRate = 44100;

   // BlockFiles are always mono
   header.channels = 1;

   // Write the file
   if (!summaryData)
      summaryData = /*BlockFile::*/CalcSummary(sampleData, sampleLen, format); //mchinen:allowing virtual override of calc summary for ODDecodeBlockFile.
   
   file.Write(&header, sizeof(header));
   file.Write(summaryData, mSummaryInfo.totalSummaryBytes);

   if( format == int24Sample )
   {
      // we can't write the buffer directly to disk, because 24-bit samples
      // on disk need to be packed, not padded to 32 bits like they are in
      // memory
      int *int24sampleData = (int*)sampleData;

      for( int i = 0; i < sampleLen; i++ )
#if wxBYTE_ORDER == wxBIG_ENDIAN
         file.Write((char*)&int24sampleData[i] + 1, 3);
#else
         file.Write((char*)&int24sampleData[i], 3);
#endif
   }
   else
   {
      // for all other sample formats we can write straight from the buffer
      // to disk
      file.Write(sampleData, sampleLen * SAMPLE_SIZE(format));
    }
    
    DEBUG_OUTPUT("Wrote simple block file");
    
    return true;
}