示例#1
0
/// Reads the specified data from the aliased file, using libsndfile,
/// and converts it to the given sample format.
/// Copied from PCMAliasBlockFIle but wxLog calls taken out for thread safety
///
/// @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
size_t ODPCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
                                size_t start, size_t len) const
{

   LockRead();

   SF_INFO info;

   if(!mAliasedFileName.IsOk()){ // intentionally silenced
      memset(data,0,SAMPLE_SIZE(format)*len);
      UnlockRead();
      return len;
   }

   memset(&info, 0, sizeof(info));

   wxString aliasPath = mAliasedFileName.GetFullPath();

   wxFile f;   // will be closed when it goes out of scope
   SFFile sf;

   if (f.Exists(aliasPath) && f.Open(aliasPath)) {
      // Even though there is an sf_open() that takes a filename, use the one that
      // takes a file descriptor since wxWidgets can open a file with a Unicode name and
      // libsndfile can't (under Windows).
      sf.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE));
   }
   // FIXME: TRAP_ERR failure of wxFile open incompletely handled in ODPCMAliasBlockFile::ReadData.


   if (!sf) {

      memset(data,0,SAMPLE_SIZE(format)*len);

      mSilentAliasLog = TRUE;
      // Set a marker to display an error message
      if (!wxGetApp().ShouldShowMissingAliasedFileWarning())
         wxGetApp().MarkAliasedFilesMissingWarning(this);

      UnlockRead();
      return len;
   }

   mSilentAliasLog=FALSE;

   // Third party library has its own type alias, check it
   static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
                 "Type sf_count_t is too narrow to hold a sampleCount");
   SFCall<sf_count_t>(sf_seek, sf.get(),
                      ( mAliasStart + start ).as_long_long(), SEEK_SET);

   wxASSERT(info.channels >= 0);
   SampleBuffer buffer(len * info.channels, floatSample);

   size_t 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 = SFCall<sf_count_t>(sf_readf_short, sf.get(), (short *)buffer.ptr(), len);

      for (int i = 0; i < framesRead; i++)
         ((short *)data)[i] =
            ((short *)buffer.ptr())[(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 = SFCall<sf_count_t>(sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
      float *bufferPtr = &((float *)buffer.ptr())[mAliasChannel];
      CopySamples((samplePtr)bufferPtr, floatSample,
                  (samplePtr)data, format,
                  framesRead, true, info.channels);
   }

   UnlockRead();
   return framesRead;
}
示例#2
0
/// 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 read
int LegacyBlockFile::ReadData(samplePtr data, sampleFormat format,
                              sampleCount start, sampleCount len) const
{
    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));

    wxFile f;   // will be closed when it goes out of scope
    SFFile sf;

    if (f.Open(mFileName.GetFullPath())) {
        // Even though there is an sf_open() that takes a filename, use the one that
        // takes a file descriptor since wxWidgets can open a file with a Unicode name and
        // libsndfile can't (under Windows).
        sf.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE));
    }

    {
        Maybe<wxLogNull> silence{};
        if (mSilentLog)
            silence.create();

        if (!sf) {

            memset(data, 0, SAMPLE_SIZE(format)*len);

            mSilentLog = TRUE;

            return len;
        }
    }
    mSilentLog=FALSE;

    sf_count_t seekstart = start +
                           (mSummaryInfo.totalSummaryBytes / SAMPLE_SIZE(mFormat));
    SFCall<sf_count_t>(sf_seek, sf.get(), seekstart , SEEK_SET);

    SampleBuffer buffer(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 = SFCall<sf_count_t>(sf_readf_short, sf.get(), (short *)data, len);
    }
    else if (format == int24Sample &&
             sf_subtype_is_integer(info.format)) {
        framesRead = SFCall<sf_count_t>(sf_readf_int, sf.get(), (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 {
示例#3
0
/// 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 read
int SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
                        sampleCount start, sampleCount len) const
{
   if (mCache.active)
   {
      //wxLogDebug("SimpleBlockFile::ReadData(): Data are already in cache.");

      if (len > mLen - start)
         len = mLen - start;
      CopySamples(
         (samplePtr)(((char*)mCache.sampleData) +
            start * SAMPLE_SIZE(mCache.format)),
         mCache.format, data, format, len);
      return len;
   } else
   {
      //wxLogDebug("SimpleBlockFile::ReadData(): Reading data from disk.");

      SF_INFO info;
      wxFile f;   // will be closed when it goes out of scope
      SFFile sf;
      {
         Maybe<wxLogNull> silence{};
         if (mSilentLog)
            silence.create();

         memset(&info, 0, sizeof(info));

         if (f.Open(mFileName.GetFullPath())) {
            // Even though there is an sf_open() that takes a filename, use the one that
            // takes a file descriptor since wxWidgets can open a file with a Unicode name and
            // libsndfile can't (under Windows).
            sf.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE));
         }
         // FIXME: TRAP_ERR failure of wxFile open incompletely handled in SimpleBlockFile::ReadData.
         // FIXME: Too much cut and paste code between the different block file types.


         if (!sf) {

            memset(data, 0, SAMPLE_SIZE(format)*len);

            mSilentLog = TRUE;

            return len;
         }
      }
      mSilentLog=FALSE;

      SFCall<sf_count_t>(sf_seek, sf.get(), start, SEEK_SET);
      SampleBuffer buffer(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 = SFCall<sf_count_t>(sf_readf_short, sf.get(), (short *)data, len);
      }
      else
      if (format == int24Sample &&
          sf_subtype_is_integer(info.format))
      {
         framesRead = SFCall<sf_count_t>(sf_readf_int, sf.get(), (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 {