int GMSynthDLL::LoadSoundBank(const char *alias, const char *fileName, int preload, float scl) { SoundBank *sb = 0; sb = SoundBank::SoundBankList.FindBank(alias); if (sb != NULL) { sb->Unlock(); sb = 0; } if (SFFile::IsSF2File(fileName)) { SFFile file; sb = file.LoadSoundBank(fileName, preload); } else if (DLSFile::IsDLSFile(fileName)) { DLSFile file; sb = file.LoadSoundBank(fileName, preload); } else return GMSYNTH_ERR_FILETYPE; if (sb == NULL) return GMSYNTH_ERR_FILEOPEN; sb->Lock(); sb->name = alias; SoundBank::SoundBankList.Insert(sb); inmgr.SetSoundBank(sb, scl); sbnk = sb; return GMSYNTH_NOERROR; }
/// 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 {
/// 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; }
/// 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 {