// --------------------------------------------------------------------------- // distillSorter (static helper) // --------------------------------------------------------------------------- // Helper for sorting Partials for distilling. // static bool distillSorter( const Partial & lhs, const Partial & rhs ) { double ldur = lhs.duration(), rdur = rhs.duration(); if ( ldur != rdur ) { return ldur > rdur; } else { // What to do for same-duration Partials? // Need to do something consistent, should look // for energy? return lhs.startTime() < rhs.startTime(); /* double lpeak = PartialUtils::peakAmp( lhs ); double rpeak = PartialUtils::peakAmp( rhs ); return lhs > rhs; */ } }
Iter find_overlapping( Partial & p, double minGapTime, Iter start, Iter end) { for ( Iter it = start; it != end; ++it ) { // skip if other partial is already sifted out. if ( (*it)->label() == 0 ) continue; // skip the source Partial: // (identity test: compare addresses) // (this is a sanity check, should not happen since // src should be at position end) Assert( (*it) != &p ); // test for overlap: if ( p.startTime() < (*it)->endTime() + minGapTime && p.endTime() + minGapTime > (*it)->startTime() ) { // Does the overlapping Partial have longer duration? // (this should never be true, since the Partials // are sorted by duration) Assert( p.duration() <= (*it)->duration() ); #if Debug_Loris debugger << "Partial starting " << p.startTime() << ", " << p.begin().breakpoint().frequency() << " ending " << p.endTime() << ", " << (--p.end()).breakpoint().frequency() << " zapped by overlapping Partial starting " << (*it)->startTime() << ", " << (*it)->begin().breakpoint().frequency() << " ending " << (*it)->endTime() << ", " << (--(*it)->end()).breakpoint().frequency() << endl; #endif return it; } } // no overlapping Partial found: return end; }
// --------------------------------------------------------------------------- // getPartial // --------------------------------------------------------------------------- // Convert any FileIOExceptions into ImportExceptions, so that clients can // reasonably expect to catch only ImportExceptions. // static void getPartial( std::istream & s, PartialList & partials, double bweCutoff ) { try { // read the Track header: TrackOnDisk tkHeader; readTrackHeader( s, tkHeader ); // create a Partial: Partial p; p.setLabel( tkHeader.label ); // keep running phase and time for Breakpoint construction: double phase = tkHeader.initialPhase; // convert time to seconds and offset by a millisecond to // allow for implied onset (Lemur analysis data was shifted // such that the earliest Partial starts at 0). double time = tkHeader.startTime * 0.001; // use this to compute phases: double prevTtnSec = 0.; // loop: read Peak, create Breakpoint, add to Partial: for ( int i = 0; i < tkHeader.numPeaks; ++i ) { // read Peak: PeakOnDisk pkData; readPeakData( s, pkData ); double frequency = pkData.frequency; double amplitude = pkData.magnitude; double bandwidth = std::min( pkData.bandwidth, 1.f ); // fix bandwidth: // Lemur used a cutoff frequency, below which // bandwidth was ignored; Loris does not, so // toss out that bogus bandwidth. if ( frequency < bweCutoff ) { amplitude *= std::sqrt(1. - bandwidth); bandwidth = 0.; } // otherwise, adjust the bandwidth value // to account for the difference in noise // scaling between Lemur and Loris; this // mess doubles the noise modulation index // without changing the sine modulation index, // see Oscillator::modulate(). else { amplitude *= std::sqrt( 1. + (3. * bandwidth) ); bandwidth = (4. * bandwidth) / ( 1. + (3. * bandwidth) ); } // update phase based on _this_ pkData's interpolated freq: phase +=2. * Pi * prevTtnSec * pkData.interpolatedFrequency; phase = std::fmod( phase, 2. * Pi ); // create Breakpoint: Breakpoint bp( frequency, amplitude, bandwidth, phase ); // insert in Partial: p.insert( time, bp ); // update time: prevTtnSec = pkData.ttn * 0.001; time += prevTtnSec; } if ( p.duration() > 0. ) { partials.push_back( p ); } /* else { debugger << "import rejecting a Partial of zero duration (" << tkHeader.numPeaks << " peaks read)" << endl; } */ } catch( FileIOException & ex ) { ex.append( "Failed to import a partial from a Lemur file." ); throw; } }