long long RealTime::realTime2Frame(const RealTime &time, unsigned int sr) { if (time < zeroTime) return -realTime2Frame(-time, sr); long long sampleRate = sr; // We like integers. The last term is always zero unless the // sample rate is greater than 1MHz, but hell, you never know... long frame = time.sec * sampleRate + (time.msec() * sampleRate) / 1000 + ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 + ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000; return frame; }
void SoundDriver::sleep(const RealTime &rt) { // The usleep man page says it's deprecated and we should use // nanosleep. And that's what we did. But it seems quite a few // people don't have nanosleep, so we're reverting to usleep. unsigned long usec = rt.sec * 1000000 + rt.usec(); usleep(usec); }
// scan on from a descriptor position bool RIFFAudioFile::scanForward(std::ifstream *file, const RealTime &time) { // sanity if (file == 0) return false; unsigned int totalSamples = m_sampleRate * time.sec + ( ( m_sampleRate * time.usec() ) / 1000000 ); unsigned int totalBytes = totalSamples * m_bytesPerFrame; m_loseBuffer = true; // do the seek file->seekg(totalBytes, std::ios::cur); if (file->eof()) return false; return true; }
void CreateTempoMapFromSegmentCommand::initialise(Segment *s) { m_oldTempi.clear(); m_newTempi.clear(); //!!! need an additional option: per-chord, per-beat, per-bar. // Let's work per-beat for the moment. Even for this, we should // probably use TimeSignature.getDivisions() std::vector<timeT> beatTimeTs; std::vector<RealTime> beatRealTimes; int startBar = m_composition->getBarNumber(s->getStartTime()); int barNo = startBar; int beat = 0; for (Segment::iterator i = s->begin(); s->isBeforeEndMarker(i); ++i) { if ((*i)->isa(Note::EventType)) { bool isNew; TimeSignature sig = m_composition->getTimeSignatureInBar(barNo, isNew); beatTimeTs.push_back(m_composition->getBarStart(barNo) + beat * sig.getBeatDuration()); if (++beat >= sig.getBeatsPerBar()) { ++barNo; beat = 0; } beatRealTimes.push_back(s->getComposition()->getElapsedRealTime ((*i)->getAbsoluteTime())); } } if (beatTimeTs.size() < 2) return ; tempoT prevTempo = 0; // set up m_oldTempi and prevTempo for (int i = m_composition->getTempoChangeNumberAt(*beatTimeTs.begin() - 1) + 1; i <= m_composition->getTempoChangeNumberAt(*beatTimeTs.end() - 1); ++i) { std::pair<timeT, tempoT> tempoChange = m_composition->getTempoChange(i); m_oldTempi[tempoChange.first] = tempoChange.second; if (prevTempo == 0) prevTempo = tempoChange.second; } RG_DEBUG << "starting tempo: " << prevTempo << endl; timeT quarter = Note(Note::Crotchet).getDuration(); for (size_t beat = 1; beat < beatTimeTs.size(); ++beat) { timeT beatTime = beatTimeTs[beat] - beatTimeTs[beat - 1]; RealTime beatRealTime = beatRealTimes[beat] - beatRealTimes[beat - 1]; // Calculate tempo to nearest qpm. // This is 60 / {quarter note duration in seconds} // = 60 / ( {beat in seconds} * {quarter in ticks} / { beat in ticks} ) // = ( 60 * {beat in ticks} ) / ( {beat in seconds} * {quarter in ticks} ) // Precision is deliberately limited to qpm to avoid silly values. double beatSec = double(beatRealTime.sec) + double(beatRealTime.usec() / 1000000.0); double qpm = (60.0 * beatTime) / (beatSec * quarter); tempoT tempo = Composition::getTempoForQpm(int(qpm + 0.001)); RG_DEBUG << "prev beat: " << beatTimeTs[beat] << ", prev beat real time " << beatRealTimes[beat] << endl; RG_DEBUG << "time " << beatTime << ", rt " << beatRealTime << ", beatSec " << beatSec << ", tempo " << tempo << endl; if (tempo != prevTempo) { m_newTempi[beatTimeTs[beat - 1]] = tempo; prevTempo = tempo; } } }
JNIEXPORT jint JNICALL Java_org_vamp_1plugins_RealTime_usec(JNIEnv *env, jobject obj) { RealTime rt = getRealTime(env, obj); return rt.usec(); }