示例#1
0
    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());
    }
示例#2
0
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();
}
示例#3
0
void FileTypeFactory::addType(AudioFile* (*function)(const QString&))
{
	AudioFile *type = function( QString() );

	mFileTypes[type->type()] = function;

	delete type;
};
示例#4
0
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;
}
示例#6
0
 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");
 }
示例#7
0
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;
};
示例#8
0
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();
    }
}
示例#9
0
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;
    }
}
示例#10
0
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;
      }
示例#11
0
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;
      }
示例#12
0
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);
}
示例#13
0
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;
}
示例#14
0
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));
	    }
	}
    }
}