void AudioSample::loadSampleData(const AudioFile& audioFile) { std::vector<int16_t> sampleData = audioFile.getSampleData(); FEA_ASSERT(sampleData.size() > 0, "Trying to load samples from a file containing no samples!"); if(!mBuffer) mBuffer = std::unique_ptr<AudioBuffer>(new AudioBuffer()); ALint format; switch(audioFile.getChannelCount()) { case 1 : format = AL_FORMAT_MONO16; break; case 2 : format = AL_FORMAT_STEREO16; break; case 4 : format = alGetEnumValue("AL_FORMAT_QUAD16"); break; case 6 : format = alGetEnumValue("AL_FORMAT_51CHN16"); break; case 7 : format = alGetEnumValue("AL_FORMAT_61CHN16"); break; case 8 : format = alGetEnumValue("AL_FORMAT_71CHN16"); break; default : format = 0; break; } // Fixes a bug on OS X supposedly if (format == -1) format = 0; alBufferData(mBuffer->getBufferId(), format, sampleData.data(), sampleData.size() * sizeof(int16_t), audioFile.getSampleRate()); }
AudioFile* AudioMixer::new_audio_file(string name, bool is_music) { if (no_audio) return NULL; string filename; void *audio; // Check if this audio file is a music file or not if (is_music) { // Load a music file... string filename = "audio/" + name + ".ogg"; audio = (void*) Mix_LoadMUS(filename.c_str()); if(audio == NULL) { printf("Unable to load Ogg file: %s\n", Mix_GetError()); exit(1); } } else { // Load a sound file... string filename = "audio/" + name + ".wav"; audio = (void*) Mix_LoadWAV(filename.c_str()); if(audio == NULL) { printf("Unable to load Wav file: %s\n", Mix_GetError()); exit(1); } } AudioFile* audiofile = new AudioFile(name, audio, is_music); if ((is_music && !music_on) || (!is_music && !sfx_on)) audiofile->toggle_mute(); audio_files.push_back(audiofile); return audio_files.back(); }
void FileTypeFactory::addType(AudioFile* (*function)(const QString&)) { AudioFile *type = function( QString() ); mFileTypes[type->type()] = function; delete type; };
QStringList ProjectPackager::getAudioFiles() { QStringList list; // get the Composition from the document, so we can iterate through it Composition *comp = &m_doc->getComposition(); // We don't particularly care about tracks here, so just iterate through the // entire Composition to find the audio segments and get the associated // file IDs from which to obtain a list of actual files. This could // conceivably pick up audio segments that are residing on MIDI tracks and // wouldn't otherwise be functional, but the important thing is to never // miss a single file that has any chance of being worth preserving. for (Composition::iterator i = comp->begin(); i != comp->end(); ++i) { if ((*i)->getType() == Segment::Audio) { AudioFileManager *manager = &m_doc->getAudioFileManager(); unsigned int id = (*i)->getAudioFileId(); AudioFile *file = manager->getAudioFile(id); // some polite sanity checking to avoid possible crashes if (!file) continue; list << file->getFilename(); } } // QStringList::removeDuplicates() would have been easy, but it's only in Qt // 4.5.0 and up. So here's the algorithm from Qt 4.5.0, courtesy of (and // originally Copyright 2009) Nokia QStringList *that = &list; int n = that->size(); int j = 0; QSet<QString> seen; seen.reserve(n); for (int i = 0; i < n; ++i) { const QString &s = that->at(i); if (seen.contains(s)) continue; seen.insert(s); if (j != i) (*that)[j] = s; ++j; } if (n != j) that->erase(that->begin() + j, that->end()); // return n - j; return list; }
void AudioSegmentInsertCommand::execute() { if (!m_segment) { // Create and insert Segment // m_segment = new Segment(Segment::Audio); m_segment->setTrack(m_track); m_segment->setStartTime(m_startTime); m_segment->setAudioStartTime(m_audioStartTime); m_segment->setAudioEndTime(m_audioEndTime); m_segment->setAudioFileId(m_audioFileId); // Set color for audio segment (DMM) // m_segment->setColourIndex(GUIPalette::AudioDefaultIndex); // Calculate end time // RealTime startTime = m_composition->getElapsedRealTime(m_startTime); RealTime endTime = startTime + m_audioEndTime - m_audioStartTime; timeT endTimeT = m_composition->getElapsedTimeForRealTime(endTime); RG_DEBUG << "AudioSegmentInsertCommand::execute : start timeT " << m_startTime << ", startTime " << startTime << ", audioStartTime " << m_audioStartTime << ", audioEndTime " << m_audioEndTime << ", endTime " << endTime << ", end timeT " << endTimeT << endl; m_segment->setEndTime(endTimeT); if (endTimeT > m_composition->getEndMarker()) { m_composition->setEndMarker(m_composition->getBarEndForTime(endTimeT)); } // Label by audio file name // AudioFile *aF = m_audioFileManager->getAudioFile(m_audioFileId); if (aF) { std::string label = aF->getLabel(); m_segment->setLabel(appendLabel(label, qstrtostr(tr("(inserted)")))); } else { m_segment->setLabel(qstrtostr( tr("unknown audio file")) ); } m_composition->addSegment(m_segment); } else { m_composition->addSegment(m_segment); } m_detached = false; }
void buffer(const AudioFile& audio_file) { Bytes data; ALenum format; ALsizei frequency; audio_file.convert(&data, &format, &frequency); alBufferData(_buffer, format, data.data(), data.size(), frequency); check_al_error("alBufferData"); }
AudioFile* FileTypeFactory::getHandle(const QString& path) { AudioFile *file = 0; foreach(AudioFile* (*function)(const QString&), mFileTypes.values()) { file = function(path); if(file->isValid()) break; delete file; file = 0; } return file; };
SegmentEraseCommand::SegmentEraseCommand(Segment *segment, AudioFileManager *mgr) : NamedCommand(tr("Erase Segment")), m_composition(segment->getComposition()), m_segment(segment), m_mgr(mgr), m_detached(false) { // If this is an audio segment, we want to make a note of // its associated file name in case we need to undo and restore // the file. if (m_segment->getType() == Segment::Audio) { unsigned int id = m_segment->getAudioFileId(); AudioFile *file = mgr->getAudioFile(id); if (file) m_audioFileName = file->getFilename(); } }
bool SoundDriver::addAudioFile(const QString &fileName, unsigned int id) { AudioFile *ins = 0; try { ins = new WAVAudioFile(id, qstrtostr(fileName), fileName); ins->open(); m_audioFiles.push_back(ins); //RG_DEBUG << "Sequencer::addAudioFile() = \"" << fileName << "\""; return true; } catch (SoundFile::BadSoundFileException e) { RG_DEBUG << "SoundDriver::addAudioFile: Failed to add audio file " << fileName << ": " << e.getMessage(); delete ins; return false; } }
Sample* ZInstrument::readSample(const QString& s, MQZipReader* uz) { if (uz) { QList<MQZipReader::FileInfo> fi = uz->fileInfoList(); buf = uz->fileData(s); if (buf.isEmpty()) { printf("Sample::read: cannot read sample data <%s>\n", qPrintable(s)); return 0; } } else { QFile f(s); if (!f.open(QIODevice::ReadOnly)) { printf("Sample::read: open <%s> failed\n", qPrintable(s)); return 0; } buf = f.readAll(); } AudioFile a; if (!a.open(buf)) { printf("open <%s> failed: %s\n", qPrintable(s), a.error()); return 0; } int channel = a.channels(); int frames = a.frames(); int sr = a.samplerate(); short* data = new short[(frames + 3) * channel]; Sample* sa = new Sample(channel, data, frames, sr); if (frames != a.read(data + channel, frames)) { printf("Sample read failed: %s\n", a.error()); delete[] data; delete sa; sa = 0; } for (int i = 0; i < channel; ++i) { data[i] = data[channel + i]; data[(frames-1) * channel + i] = data[(frames-3) * channel + i]; data[(frames-2) * channel + i] = data[(frames-3) * channel + i]; } return sa; }
bool Sample::decompressOggVorbis(char* src, int size) { AudioFile af; QByteArray ba(src, size); start = 0; end = 0; if (!af.open(ba)) { qDebug("Sample::decompressOggVorbis: open failed: %s", af.error()); return false; } int frames = af.frames(); data = new short[frames * af.channels()]; if (frames != af.readData(data, frames)) { qDebug("Sample read failed: %s", af.error()); delete[] data; data = 0; } end = frames - 1; if (loopend > end ||loopstart >= loopend || loopstart <= start) { /* can pad loop by 8 samples and ensure at least 4 for loop (2*8+4) */ if ((end - start) >= 20) { loopstart = start + 8; loopend = end - 8; } else { // loop is fowled, sample is tiny (can't pad 8 samples) loopstart = start + 1; loopend = end - 1; } } if ((end - start) < 8) { qDebug("invalid sample"); setValid(false); } return true; }
void SoundDriver::initialiseAudioQueue(const std::vector<MappedEvent> &events) { AudioPlayQueue *newQueue = new AudioPlayQueue(); for (std::vector<MappedEvent>::const_iterator i = events.begin(); i != events.end(); ++i) { // Check for existence of file - if the sequencer has died // and been restarted then we're not always loaded up with // the audio file references we should have. In the future // we could make this just get the gui to reload our files // when (or before) this fails. // AudioFile *audioFile = getAudioFile(i->getAudioID()); if (audioFile) { MappedAudioFader *fader = dynamic_cast<MappedAudioFader*> (getMappedStudio()->getAudioFader(i->getInstrument())); if (!fader) { RG_DEBUG << "WARNING: SoundDriver::initialiseAudioQueue: no fader for audio instrument " << i->getInstrument(); continue; } int channels = fader->getPropertyList( MappedAudioFader::Channels)[0].toInt(); //#define DEBUG_PLAYING_AUDIO #ifdef DEBUG_PLAYING_AUDIO RG_DEBUG << "Creating playable audio file: id " << audioFile->getId() << ", event time " << i->getEventTime() << ", time now " << getSequencerTime() << ", start marker " << i->getAudioStartMarker() << ", duration " << i->getDuration() << ", instrument " << i->getInstrument() << " channels " << channels; #endif RealTime bufferLength = getAudioReadBufferLength(); size_t bufferFrames = (size_t)RealTime::realTime2Frame (bufferLength, getSampleRate()); PlayableAudioFile *paf = 0; try { paf = new PlayableAudioFile(i->getInstrument(), audioFile, i->getEventTime(), i->getAudioStartMarker(), i->getDuration(), bufferFrames, size_t(getSmallFileSize()) * 1024, channels, int(getSampleRate())); } catch (...) { continue; } paf->setRuntimeSegmentId(i->getRuntimeSegmentId()); if (i->isAutoFading()) { paf->setAutoFade(true); paf->setFadeInTime(i->getFadeInTime()); paf->setFadeOutTime(i->getFadeInTime()); //#define DEBUG_AUTOFADING #ifdef DEBUG_AUTOFADING RG_DEBUG << "SoundDriver::initialiseAudioQueue - " << "PlayableAudioFile is AUTOFADING - " << "in = " << i->getFadeInTime() << ", out = " << i->getFadeOutTime(); #endif } #ifdef DEBUG_AUTOFADING else { RG_DEBUG << "PlayableAudioFile has no AUTOFADE"; } #endif newQueue->addScheduled(paf); } else { RG_DEBUG << "SoundDriver::initialiseAudioQueue - " << "can't find audio file reference for id " << i->getAudioID(); RG_DEBUG << "SoundDriver::initialiseAudioQueue - " << "try reloading the current Rosegarden file"; } } RG_DEBUG << "SoundDriver::initialiseAudioQueue -- new queue has " << newQueue->size() << " files"; if (newQueue->empty()) { if (m_audioQueue->empty()) { delete newQueue; return ; } } AudioPlayQueue *oldQueue = m_audioQueue; m_audioQueue = newQueue; if (oldQueue) m_audioQueueScavenger.claim(oldQueue); }
bool AudioPeaksThread::process() { #ifdef DEBUG_AUDIO_PEAKS_THREAD RG_DEBUG << "AudioPeaksThread::process()"; #endif // ??? There appears to be a bug that causes this to run one extra time // at the beginning of a set of updates. It's really easy to see // if you enable the sleep(5) below. The first result takes 10 // seconds to appear. Then the subsequent results take 5 seconds // each. It's as if a garbage entry is always at the head of the // queue. if (!m_queue.empty()) { int failed = 0; int inQueue = 0; //int count = 0; m_mutex.lock(); // process 1st request and leave inQueue = m_queue.size(); RequestQueue::iterator i = m_queue.begin(); // i->first is width, which we use only to provide an ordering to // ensure we do smaller files first. We don't use it here. RequestRec &rec = i->second; int token = rec.first; Request req = rec.second; m_mutex.unlock(); // DEBUG. Slow things down for testing. //sleep(5); std::vector<float> results; try { #ifdef DEBUG_AUDIO_PEAKS_THREAD RG_DEBUG << "AudioPeaksThread::process() file id " << req.audioFileId; #endif // Requires thread-safe AudioFileManager::getPreview // ??? rename: getPeaks() results = m_manager->getPreview(req.audioFileId, req.audioStartTime, req.audioEndTime, req.width, req.showMinima); } catch (AudioFileManager::BadAudioPathException e) { #ifdef DEBUG_AUDIO_PEAKS_THREAD RG_DEBUG << "AudioPeaksThread::process: failed to get peaks for audio file " << req.audioFileId << ": bad audio path: " << e.getMessage(); #endif // OK, we hope this just means we're still recording -- so // leave this one in the queue ++failed; } catch (PeakFileManager::BadPeakFileException e) { #ifdef DEBUG_AUDIO_PEAKS_THREAD RG_DEBUG << "AudioPeaksThread::process: failed to get peaks for audio file " << req.audioFileId << ": bad peak file: " << e.getMessage(); #endif // As above ++failed; } m_mutex.lock(); // We need to check that the token is still in the queue // (i.e. hasn't been cancelled). Otherwise we shouldn't notify bool found = false; for (RequestQueue::iterator i = m_queue.begin(); i != m_queue.end(); ++i) { if (i->second.first == token) { found = true; m_queue.erase(i); break; } } if (found) { AudioFile *audioFile = m_manager->getAudioFile(req.audioFileId); // If there's an audio file to work with if (audioFile != NULL) { unsigned int channels = audioFile->getChannels(); m_results[token] = ResultsPair(channels, results); QObject *notify = req.notify; QApplication::postEvent(notify, new AudioPeaksReadyEvent(token)); } } m_mutex.unlock(); if (failed > 0 && failed == inQueue) { #ifdef DEBUG_AUDIO_PEAKS_THREAD RG_DEBUG << "AudioPeaksThread::process() - return true"; #endif return true; // delay and try again } } #ifdef DEBUG_AUDIO_PEAKS_THREAD RG_DEBUG << "AudioPeaksThread::process() - return false"; #endif return false; }
void match(AudioFile &needle, AudioFile &haystack, std::vector<pair<size_t, double> > &results) { std::vector<short> small; std::vector<short> large; std::vector<int64_t> smallPrefixSum; std::vector<int64_t> largePrefixSum; needle.getSamplesForChannel(0, small); prefixSquareSum(small, smallPrefixSum); proxyFFT<short, double> smallFFT(small); smallFFT.transform(); size_t largeTotalSize = haystack.getNumberOfSamplesPrChannel(); // vector<int64_t> maxSamplesBegin(largeTotalSize/small.size()); // vector<int64_t> maxSamplesEnd(largeTotalSize/small.size()); vector<Record> maxSamplesBegin(largeTotalSize/small.size()); vector<Record> maxSamplesEnd(largeTotalSize/small.size()); size_t stillToRead = largeTotalSize; AudioStream hayStream = haystack.getStream(0); size_t pieces = 13; for (int j = 0; ; ++j) { hayStream.read(pieces*small.size(), large); prefixSquareSum(large, largePrefixSum); size_t numberOfParts = large.size()/small.size(); size_t idxAdd = j*pieces; // Progress information std::cout << '\r' << setw(8) << ((largeTotalSize-stillToRead)+0.0)/largeTotalSize*100 << " %"; std::cout.flush(); stillToRead -= large.size(); for (size_t ii = 0; ii < numberOfParts*small.size(); ii += small.size()) { //do stuff.. proxyFFT<short, double> largeFFT(large.begin()+ii, large.begin()+ii+small.size()); vector<complex<double> > outBegin; vector<complex<double> > outEnd; //std::cout << "TEST1" << std::endl; cross_correlation(largeFFT, smallFFT, outBegin); cross_correlation(smallFFT, largeFFT, outEnd); size_t maxSampleBegin = 0; double maxNormFactorBegin = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin(), smallPrefixSum.end(), largePrefixSum.begin()+ii, largePrefixSum.begin()+small.size()+ii); for (size_t i = 0 ; i < outBegin.size(); ++i) { double normFactor = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin(), smallPrefixSum.end()-i, largePrefixSum.begin()+i+ii, largePrefixSum.begin()+ii+small.size()); if (outBegin[maxSampleBegin].real()/maxNormFactorBegin < outBegin[i].real()/normFactor) { maxSampleBegin = i; maxNormFactorBegin = normFactor; } } //std::cout << "TEST2" << std::endl; size_t maxSampleEnd = 0; double maxNormFactorEnd = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin(), smallPrefixSum.end(), largePrefixSum.begin()+ii, largePrefixSum.begin()+small.size()+ii); for (size_t i = 0 ; i < outEnd.size(); ++i) { double normFactor = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin()+i, smallPrefixSum.end(), largePrefixSum.begin()+ii, largePrefixSum.begin()-i+ii+small.size()); if (outEnd[maxSampleEnd].real()/maxNormFactorEnd < outEnd[i].real()/normFactor) { maxSampleEnd = i; maxNormFactorEnd = normFactor; } } maxSamplesBegin[ii/small.size()+idxAdd] = Record(maxNormFactorBegin, outBegin[maxSampleBegin].real(), small.size() - maxSampleBegin); maxSamplesEnd[ii/small.size()+idxAdd] = Record(maxNormFactorEnd, outEnd[maxSampleEnd].real(), small.size() - maxSampleEnd); } if (numberOfParts != pieces) break; } std::cout << '\r' << setw(8) << 100 << "%" << std::endl; // // FIXME: special case. // // small size does not divide large size // // => last piece is not analysed. // // fix this. for (size_t i = 0; i < maxSamplesBegin.size()-1; ++i) { double val = (maxSamplesBegin[i].cv + maxSamplesEnd[i+1].cv)/(maxSamplesBegin[i].nf + maxSamplesEnd[i+1].nf); if (val > 0.3) { // arbitrary magic number. Seems to work well. size_t length = maxSamplesBegin[i].s + maxSamplesEnd[i+1].s; if (length <= small.size() && length >= THRESHHOLD*small.size()) { // length must be appropriate results.push_back(make_pair((i+1)*small.size()-maxSamplesBegin[i].s, val)); } } } }