Beispiel #1
0
KeyFinderResultWrapper keyDetectionProcess(const AsyncFileObject& object){

  KeyFinderResultWrapper result;
  result.batchRow = object.batchRow;

  // initialise stream and decode file into it.
  KeyFinder::AudioData* audio = NULL;
  AudioFileDecoder* decoder = NULL;
  try{
    decoder = AudioFileDecoder::getDecoder();
  }catch(KeyFinder::Exception& e){
    delete decoder;
    result.errorMessage = QString(e.what().c_str());
    return result;
  }

  try{
    audio = decoder->decodeFile(object.filePath);
    delete decoder;
  }catch(KeyFinder::Exception& e){
    delete audio;
    delete decoder;
    result.errorMessage = QString(e.what().c_str());
    return result;
  }

  // make audio stream monaural ahead of downsample to reduce load
  audio->reduceToMono();

  // downsample if necessary
  if(object.prefs.getDFactor() > 1){
    Downsampler* ds = Downsampler::getDownsampler(object.prefs.getDFactor(),audio->getFrameRate(),object.prefs.getLastFreq());
    try{
      audio = ds->downsample(audio,object.prefs.getDFactor());
    }catch(KeyFinder::Exception& e){
      delete audio;
      delete ds;
      result.errorMessage = QString(e.what().c_str());
      return result;
    }
    delete ds;
  }

  KeyFinder::KeyFinder* kf = LibKeyFinderSingleton::getInstance()->getKeyFinder();
  result.core = kf->findKey(*audio, object.prefs.core);

  delete audio;

  return result;
}
KeyFinderResultWrapper keyDetectionProcess(const AsyncFileObject& object) {

  KeyFinderResultWrapper result;
  result.batchRow = object.batchRow;

  AudioFileDecoder* decoder = NULL;
  try {

    decoder = new AudioFileDecoder(object.filePath, object.prefs.getMaxDuration());

  } catch (std::exception& e) {

    delete decoder;
    result.errorMessage = QString(e.what());
    return result;

  } catch (...) {

    delete decoder;
    result.errorMessage = "Unknown exception initialising decoder";
    return result;
  }

  KeyFinder::Workspace workspace;

  static KeyFinder::KeyFinder kf;

  try {

    while (true) {

      KeyFinder::AudioData* tempAudio = decoder->decodeNextAudioPacket();
      if (tempAudio == NULL) break;

      kf.progressiveChromagram(*tempAudio, workspace);
      delete tempAudio;
    }

    delete decoder;
    decoder = NULL;

    kf.finalChromagram(workspace);
    result.fullChromagram = KeyFinder::Chromagram(*workspace.chromagram);
    result.core = kf.keyOfChromagram(workspace);

  } catch (std::exception& e) {

    if (decoder != NULL) delete decoder;
    result.errorMessage = QString(e.what());
    return result;

  } catch (...) {

    if (decoder != NULL) {
      delete decoder;
      result.errorMessage = "Unknown exception while decoding";
    } else {
      result.errorMessage = "Unknown exception while analysing";
    }

    return result;
  }

  return result;
}
KeyFinderResultWrapper keyDetectionProcess(const AsyncFileObject& object) {

  KeyFinderResultWrapper result;
  result.batchRow = object.batchRow;

  AudioFileDecoder* decoder = NULL;
  try {
    decoder = new AudioFileDecoder(object.filePath, object.prefs.getMaxDuration());
  } catch (std::exception& e) {
    delete decoder;
    result.errorMessage = QString(e.what());
    return result;
  } catch (...) {
    delete decoder;
    result.errorMessage = "Unknown exception initialising decoder";
    return result;
  }

  KeyFinder::Workspace workspace;
  static KeyFinder::KeyFinder kf;
  try {
    while (true) {
      KeyFinder::AudioData* tempAudio = decoder->decodeNextAudioPacket();
      if (tempAudio == NULL) break;
      kf.progressiveChromagram(*tempAudio, workspace, object.prefs.core);
      delete tempAudio;
    }
    delete decoder;
    decoder = NULL;
    kf.finalChromagram(workspace, object.prefs.core);
    result.fullChromagram = KeyFinder::Chromagram(*workspace.chromagram);
    result.core = kf.keyOfChromagram(workspace, object.prefs.core);
    result.oneOctaveChromagram = result.fullChromagram;
    result.oneOctaveChromagram.reduceToOneOctave();
  } catch (std::exception& e) {
    if (decoder != NULL) delete decoder;
    result.errorMessage = QString(e.what());
    return result;
  } catch (...) {
    if (decoder != NULL) {
      delete decoder;
      result.errorMessage = "Unknown exception while decoding";
    } else {
      result.errorMessage = "Unknown exception while analysing";
    }
    return result;
  }

  for (unsigned int i = 0; i < result.core.segments.size(); i++) {
    qDebug(
      "Chroma vector for segment %d of file %s: [%.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f]",
      i, object.filePath.toUtf8().constData(),
      result.core.segments[i].chromaVector[0],  result.core.segments[i].chromaVector[1],
      result.core.segments[i].chromaVector[2],  result.core.segments[i].chromaVector[3],
      result.core.segments[i].chromaVector[4],  result.core.segments[i].chromaVector[5],
      result.core.segments[i].chromaVector[6],  result.core.segments[i].chromaVector[7],
      result.core.segments[i].chromaVector[8],  result.core.segments[i].chromaVector[9],
      result.core.segments[i].chromaVector[10], result.core.segments[i].chromaVector[11]
    );
  }

  return result;
}
void KeyFinderWorkerThread::run(){
	if(!haveParams){
		emit failed("No parameters.");
		return;
	}
	// initialise stream and decode file into it
	AudioStream* astrm = NULL;
  AudioFileDecoder* dec = AudioFileDecoder::getDecoder(filePath.toUtf8().data());
	try{
    astrm = dec->decodeFile(filePath.toUtf8().data());
	}catch(Exception){
		delete astrm;
		delete dec;
		emit failed("Could not decode file.");
		return;
	}
	delete dec;
	emit decoded();

	// make audio stream monaural
	astrm->reduceToMono();
	emit madeMono();

	// downsample if necessary
	if(prefs.getDFactor() > 1){
		Downsampler* ds = Downsampler::getDownsampler(prefs.getDFactor(),astrm->getFrameRate(),prefs.getLastFreq());
		try{
			astrm = ds->downsample(astrm,prefs.getDFactor());
		}catch(Exception){
			delete astrm;
			delete ds;
			emit failed("Downsampler failed.");
			return;
		}
		delete ds;
		emit downsampled();
	}

	// start spectrum analysis
	SpectrumAnalyser* sa = NULL;
  Chromagram* ch = NULL;
  sa = SpectrumAnalyserFactory::getInstance()->getSpectrumAnalyser(astrm->getFrameRate(),prefs);
  ch = sa->chromagram(astrm);
  delete astrm; // note we don't delete the spectrum analyser; it stays in the centralised factory for reuse.
  ch->reduceTuningBins(prefs);
	emit producedFullChromagram(*ch);

	// reduce chromagram
	ch->reduceToOneOctave(prefs);
	emit producedOneOctaveChromagram(*ch);

	// get energy level across track to weight segments
	std::vector<float> loudness(ch->getHops());
	for(int h=0; h<ch->getHops(); h++)
		for(int b=0; b<ch->getBins(); b++)
			loudness[h] += ch->getMagnitude(h,b);

	// get harmonic change signal
	Segmentation* hcdf = Segmentation::getSegmentation(prefs);
	std::vector<double> harmonicChangeSignal = hcdf->getRateOfChange(ch,prefs);
	emit producedHarmonicChangeSignal(harmonicChangeSignal);

	// get track segmentation
  std::vector<int> changes = hcdf->getSegments(harmonicChangeSignal,prefs);
  changes.push_back(ch->getHops()); // It used to be getHops()-1. But this doesn't crash. So we like it.

	// batch output of keychange locations for Beatles experiment
	//for(int i=1; i<changes.size(); i++) // don't want the leading zero
	//	std::cout << filePath.substr(53) << "\t" << std::fixed << std::setprecision(2) << changes[i]*(prefs.getHopSize()/(44100.0/prefs.getDFactor())) << std::endl;
	// end experiment output

	// get key estimates for segments
	KeyClassifier hc(prefs);
	std::vector<int> keys(0);
	std::vector<float> keyWeights(24);
  for(int i=0; i<(signed)changes.size()-1; i++){
    std::vector<double> chroma(ch->getBins());
		for(int j=changes[i]; j<changes[i+1]; j++)
			for(int k=0; k<ch->getBins(); k++)
        chroma[k] += ch->getMagnitude(j,k);
    int key = hc.classify(chroma);
    for(int j=changes[i]; j<changes[i+1]; j++){
			keys.push_back(key);
			if(key < 24) // ignore parts that were classified as silent
				keyWeights[key] += loudness[j];
    }
	}
	keys.push_back(keys[keys.size()-1]); // put last key on again to match length of track
	delete ch;
	emit producedKeyEstimates(keys);

	// get global key
	int mostCommonKey = 24;
	float mostCommonKeyWeight = 0.0;
	for(int i=0; i<(signed)keyWeights.size(); i++){
		if(keyWeights[i] > mostCommonKeyWeight){
			mostCommonKeyWeight = keyWeights[i];
			mostCommonKey = i;
		}
	}
	emit producedGlobalKeyEstimate(mostCommonKey);
	return;
}