Exemplo n.º 1
0
static void setmsounders(sounder *dst, int ndst, const msounder *src, int nsrc){
	int i;
	msounder *list[numof(msounders)];
	assert(nsrc <= numof(list));
	for(i = 0; i < nsrc; i++)
		list[i] = &src[i];
	qsort(list, numof(list), sizeof(*list), louder);
	for(i = 0; i < nsrc; i++){
		unsigned short ld;
		msounder *ms = list[i];
		ld = 256 * loudness(ms, g_listener);
		if(numof(sounders) <= list[i]->serial){
			int j;
			for(j = 0; j < ndst; j++) if(!dst[j].priority && dst[j].vol < ld){
				list[i]->serial = j;
				break;
			}
		}
		else if(ld <= 0)
			list[i]->serial = numof(sounders);
		if(list[i]->serial < numof(sounders)){
			sounder *s = &dst[list[i]->serial];
			s->src = list[i]->src;
		}
		/* set contents of sounder by msounder */
		/*ms->src += */
	}
}
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;
}
Exemplo n.º 3
0
static int louder(const msounder **a, const msounder **b){
	double la, lb;
	la = loudness(*a, g_listener);
	lb = loudness(*b, g_listener);
	return la < lb ? 1 : lb < la ? -1 : 0;
}
int main(int argc, char** argv)
{
    bool validToProcess = false;
    bool showTime = false;
    bool enableOptimization = true;
    std::vector<int> standards;
    std::vector<std::string> filenames;

    time_t start, end;

    for(int i = 1; i < argc; i++)
    {

        if(strcmp(argv[i], "--progress") == 0)
        {
            showProgress = true;
        }
        if(strcmp(argv[i], "--verbose") == 0)
        {
            showProgress = true;
            showResults = true;
        }
        if(strcmp(argv[i], "--time") == 0)
        {
            showTime = true;
        }
        if(strcmp(argv[i], "--disable-optimization") == 0)
        {
            enableOptimization = false;
        }
        if(strncmp(argv[i], "--standard=", 11) == 0)
        {
            if(strcmp(argv[i], "--standard=cst") == 0)
            {
                standards.push_back(0);
            }
            else
            {
                if(strcmp(argv[i], "--standard=ebu") == 0)
                {
                    standards.push_back(1);
                }
                else
                {
                    if(strcmp(argv[i], "--standard=atsc") == 0)
                    {
                        standards.push_back(2);
                    }
                    else
                    {
                        std::cout << "Error: unknown standard specified in command line" << std::endl;
                        return -100;
                    }
                }
            }
        }
        if(standards.empty())
        {
            standards.push_back(1); // default standard : EBU R128
        }
        std::string ext(argv[i]);
        ext.erase(0, ext.length() - 5);
        std::string ext4 = ext;
        ext4.erase(0, 1);
        if(strcmp(ext.c_str(), ".aiff") == 0 || strcmp(ext4.c_str(), ".aif") == 0 || strcmp(ext4.c_str(), ".wav") == 0)
        {
            filenames.push_back(argv[i]);
            validToProcess = true;
        }
    }
    if(validToProcess)
    {
        for(size_t i = 0; i < filenames.size(); i++)
        {
            std::cout << filenames.at(i) << std::endl;

            std::string filename(filenames.at(i));
            if(filename.at(filename.length() - 4) == '.')
                filename.erase(filename.length() - 4, 4);
            else if(filename.at(filename.length() - 5) == '.')
                filename.erase(filename.length() - 5, 5);

            filename.append("_PLoud.xml");
            Loudness::tools::WriteXml writerXml(filename, filenames.at(i));

            for(size_t j = 0; j < standards.size(); j++)
            {
                Loudness::io::SoundFile audioFile;
                Loudness::analyser::LoudnessLevels levels =
                    standards.at(j) == 0 ? Loudness::analyser::LoudnessLevels::Loudness_CST_R017()
                                         : standards.at(j) == 1 ? Loudness::analyser::LoudnessLevels::Loudness_EBU_R128()
                                                                : Loudness::analyser::LoudnessLevels::Loudness_ATSC_A85();

                Loudness::analyser::LoudnessAnalyser loudness(levels);
                if(!audioFile.open_read(filenames.at(i).c_str()))
                {
                    time(&start);
                    Loudness::io::AnalyseFile analyser(loudness, audioFile);
                    analyser.enableOptimization(enableOptimization);
                    analyser(progress);
                    time(&end);
                    if(showResults)
                        loudness.printPloudValues();
                    audioFile.close();
                    writerXml.writeResults("unknown", loudness);
                    double dif = difftime(end, start);
                    if(showTime)
                        std::cout << "processing time: " << dif << " seconds." << std::endl;
                }
            }
        }
    }
    else
    {
        std::cout << "Loudness Analyser" << std::endl;
        std::cout << "Author: Marc-Antoine ARNAUD" << std::endl << std::endl;
        std::cout << "Common usage :" << std::endl;
        std::cout << "\tloudness-analyser [options] filename.ext" << std::endl << std::endl;
        std::cout << "Options :" << std::endl;
        std::cout << "\t--standard=ebu/cst/atsc : select one standard to validate the Loudness" << std::endl;
        std::cout << "\t\t\tebu:  EBU R 128 (default)" << std::endl;
        std::cout << "\t\t\tcst:  CST RT 017" << std::endl;
        std::cout << "\t\t\tatsc: ATSC A/85" << std::endl;
        return -1;
    }
    return 0;
}