void CueControl::updateIndicators() { // No need for mutex lock because we are only touching COs. double cueMode = m_pCueMode->get(); if (cueMode == CUE_MODE_DENON || cueMode == CUE_MODE_NUMARK) { // Cue button is only lit at cue point bool playing = m_pPlayButton->get() > 0; if (isTrackAtCue()) { // at cue point if (!playing) { m_pCueIndicator->setBlinkValue(ControlIndicator::ON); m_pPlayIndicator->setBlinkValue(ControlIndicator::OFF); } } else { m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); if (!playing) { if (getCurrentSample() < getTotalSamples() && cueMode != CUE_MODE_NUMARK) { // Play will move cue point m_pPlayIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_500MS); } else { // At track end m_pPlayIndicator->setBlinkValue(ControlIndicator::OFF); } } } } else { // Here we have CUE_MODE_PIONEER or CUE_MODE_MIXXX // default to Pioneer mode if (!m_bPreviewing) { bool playing = m_pPlayButton->get() > 0; if (!playing) { if (!isTrackAtCue()) { if (getCurrentSample() < getTotalSamples()) { if (cueMode == CUE_MODE_MIXXX) { // in Mixxx mode Cue Button is flashing slow if CUE will move Cue point m_pCueIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_500MS); } else { // in Pioneer mode Cue Button is flashing fast if CUE will move Cue point m_pCueIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_250MS); } } else { // At track end m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); } } else if (m_pCuePoint->get() != -1) { // Next Press is preview m_pCueIndicator->setBlinkValue(ControlIndicator::ON); } } } } }
void CueControl::cueCDJ(double v) { // This is how Pioneer cue buttons work: // If pressed while playing, stop playback and go to cue. // If pressed while stopped and at cue, play while pressed. // If pressed while stopped and not at cue, set new cue point. // If play is pressed while holding cue, the deck is now playing. (Handled in playFromCuePreview().) QMutexLocker lock(&m_mutex); bool playing = (m_pPlayButton->get() == 1.0); if (v) { if (playing || getCurrentSample() >= getTotalSamples()) { // Jump to cue when playing or when at end position // Just in case. m_bPreviewing = false; m_pPlayButton->set(0.0); // Need to unlock before emitting any signals to prevent deadlock. lock.unlock(); seekAbs(m_pCuePoint->get()); } else if (isTrackAtCue()) { // pause at cue point m_bPreviewing = true; m_pPlayButton->set(1.0); } else { // Pause not at cue point and not at end position cueSet(v); // Just in case. m_bPreviewing = false; // If quantize is enabled, jump to the cue point since it's not // necessarily where we currently are if (m_pQuantizeEnabled->get() > 0.0) { lock.unlock(); // prevent deadlock. // Enginebuffer will quantize more exactly than we can. seekAbs(m_pCuePoint->get()); } } } else if (m_bPreviewing) { m_bPreviewing = false; m_pPlayButton->set(0.0); // Need to unlock before emitting any signals to prevent deadlock. lock.unlock(); seekAbs(m_pCuePoint->get()); } // indicator may flash because the delayed adoption of seekAbs // Correct the Indicator set via play if (m_pLoadedTrack && !playing) { m_pCueIndicator->setBlinkValue(ControlIndicator::ON); } else { m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); } }
void CueControl::cuePlay(double v) { // This is how CUP button works: // If freely playing (i.e. playing and platter NOT being touched), press to go to cue and stop. // If not freely playing (i.e. stopped or platter IS being touched), press to go to cue and stop. // On release, start playing from cue point. QMutexLocker lock(&m_mutex); const auto freely_playing = m_pPlay->toBool() && !getEngineBuffer()->getScratching(); // pressed if (v) { if (freely_playing) { m_bPreviewing = false; m_pPlay->set(0.0); // Need to unlock before emitting any signals to prevent deadlock. lock.unlock(); seekAbs(m_pCuePoint->get()); } else if (!isTrackAtCue() && getCurrentSample() <= getTotalSamples()) { // Pause not at cue point and not at end position cueSet(v); // Just in case. m_bPreviewing = false; m_pPlay->set(0.0); // If quantize is enabled, jump to the cue point since it's not // necessarily where we currently are if (m_pQuantizeEnabled->get() > 0.0) { lock.unlock(); // prevent deadlock. // Enginebuffer will quantize more exactly than we can. seekAbs(m_pCuePoint->get()); } } } else if (isTrackAtCue()){ m_bPreviewing = false; m_pPlay->set(1.0); lock.unlock(); } }
size_t SpikeChannel::getChannelDataSize() const { return getTotalSamples()*sizeof(float); }
double CueControl::updateIndicatorsAndModifyPlay(double play, bool playPossible) { QMutexLocker lock(&m_mutex); double cueMode = m_pCueMode->get(); if ((cueMode == CUE_MODE_DENON || cueMode == CUE_MODE_NUMARK) && play > 0.0 && playPossible && m_pPlayButton->get() == 0.0) { // in Denon mode each play from pause moves the cue point // if not previewing cueSet(1.0); } // when previewing, "play" was set by cue button, a following toggle request // (play = 0.0) is used for latching play. bool previewing = false; if (m_bPreviewing || m_bPreviewingHotcue) { if (play == 0.0) { // play latch request: stop previewing and go into normal play mode. m_bPreviewing = false; m_bHotcueCancel = true; play = 1.0; } else { previewing = true; } } if (!playPossible) { // play not possible play = 0.0; m_pPlayIndicator->setBlinkValue(ControlIndicator::OFF); m_pStopButton->set(0.0); } else if (play && !previewing) { // Play: Indicates a latched Play m_pPlayIndicator->setBlinkValue(ControlIndicator::ON); m_pStopButton->set(0.0); } else { // Pause: m_pStopButton->set(1.0); if (cueMode == CUE_MODE_DENON) { if (isTrackAtCue()) { m_pPlayIndicator->setBlinkValue(ControlIndicator::OFF); } else { // Flashing indicates that a following play would move cue point m_pPlayIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_500MS); } } else if (cueMode == CUE_MODE_MIXXX || cueMode == CUE_MODE_NUMARK) { m_pPlayIndicator->setBlinkValue(ControlIndicator::OFF); } else { // Flashing indicates that play is possible in Pioneer mode m_pPlayIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_500MS); } } if (cueMode != CUE_MODE_DENON && cueMode != CUE_MODE_NUMARK) { if (m_pCuePoint->get() != -1) { if (play == 0.0 && !isTrackAtCue() && getCurrentSample() < getTotalSamples()) { if (cueMode == CUE_MODE_MIXXX) { // in Mixxx mode Cue Button is flashing slow if CUE will move Cue point m_pCueIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_500MS); } else { // in Pioneer mode Cue Button is flashing fast if CUE will move Cue point m_pCueIndicator->setBlinkValue(ControlIndicator::RATIO1TO1_250MS); } } else { m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); } } else { m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); } } m_pPlayStutter->set(play); return play; }
status_t FLACParser::init() { // setup libFLAC parser mDecoder = FLAC__stream_decoder_new(); if (mDecoder == NULL) { // The new should succeed, since probably all it does is a malloc // that always succeeds in Android. But to avoid dependence on the // libFLAC internals, we check and log here. LOGE("new failed"); return NO_INIT; } FLAC__stream_decoder_set_md5_checking(mDecoder, false); FLAC__stream_decoder_set_metadata_ignore_all(mDecoder); FLAC__stream_decoder_set_metadata_respond( mDecoder, FLAC__METADATA_TYPE_STREAMINFO); FLAC__stream_decoder_set_metadata_respond( mDecoder, FLAC__METADATA_TYPE_PICTURE); FLAC__stream_decoder_set_metadata_respond( mDecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__StreamDecoderInitStatus initStatus; initStatus = FLAC__stream_decoder_init_stream( mDecoder, read_callback, seek_callback, tell_callback, length_callback, eof_callback, write_callback, metadata_callback, error_callback, (void *) this); if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) { // A failure here probably indicates a programming error and so is // unlikely to happen. But we check and log here similarly to above. LOGE("init_stream failed %d", initStatus); return NO_INIT; } // parse all metadata if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) { LOGE("end_of_metadata failed"); return NO_INIT; } if (mStreamInfoValid) { // check channel count switch (getChannels()) { case 1: case 2: break; default: LOGE("unsupported channel count %u", getChannels()); return NO_INIT; } // check bit depth switch (getBitsPerSample()) { case 8: case 16: case 24: break; default: LOGE("unsupported bits per sample %u", getBitsPerSample()); return NO_INIT; } // check sample rate switch (getSampleRate()) { case 8000: case 11025: case 12000: case 16000: case 22050: case 24000: case 32000: case 44100: case 48000: break; default: // 96000 would require a proper downsampler in AudioFlinger LOGE("unsupported sample rate %u", getSampleRate()); return NO_INIT; } // configure the appropriate copy function, defaulting to trespass static const struct { unsigned mChannels; unsigned mBitsPerSample; void (*mCopy)(short *dst, const int *const *src, unsigned nSamples); } table[] = { { 1, 8, copyMono8 }, { 2, 8, copyStereo8 }, { 1, 16, copyMono16 }, { 2, 16, copyStereo16 }, { 1, 24, copyMono24 }, { 2, 24, copyStereo24 }, }; for (unsigned i = 0; i < sizeof(table)/sizeof(table[0]); ++i) { if (table[i].mChannels == getChannels() && table[i].mBitsPerSample == getBitsPerSample()) { mCopy = table[i].mCopy; break; } } // populate track metadata if (mTrackMetadata != 0) { mTrackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); mTrackMetadata->setInt32(kKeyChannelCount, getChannels()); mTrackMetadata->setInt32(kKeySampleRate, getSampleRate()); // sample rate is non-zero, so division by zero not possible mTrackMetadata->setInt64(kKeyDuration, (getTotalSamples() * 1000000LL) / getSampleRate()); } } else { LOGE("missing STREAMINFO"); return NO_INIT; } if (mFileMetadata != 0) { mFileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC); } return OK; }
void VinylControlControl::slotControlVinylSeek(double change) { if (isnan(change) || change > 1.14 || change < -0.14) { // This seek is ridiculous. return; } double total_samples = getTotalSamples(); double new_playpos = round(change*total_samples); // Do nothing if no track is loaded. if (!m_pCurrentTrack) { return; } if (m_pControlVinylEnabled->get() > 0.0 && m_pControlVinylMode->get() == MIXXX_VCMODE_RELATIVE) { int cuemode = (int)m_pControlVinylCueing->get(); //if in preroll, always seek if (new_playpos < 0) { seek(change); return; } switch (cuemode) { case MIXXX_RELATIVE_CUE_OFF: return; // If off, do nothing. case MIXXX_RELATIVE_CUE_ONECUE: //if onecue, just seek to the regular cue seekExact(m_pCurrentTrack->getCuePoint()); return; case MIXXX_RELATIVE_CUE_HOTCUE: // Continue processing in this function. break; default: qWarning() << "Invalid vinyl cue setting"; return; } double distance = 0; int nearest_playpos = -1; QList<Cue*> cuePoints = m_pCurrentTrack->getCuePoints(); QListIterator<Cue*> it(cuePoints); while (it.hasNext()) { Cue* pCue = it.next(); if (pCue->getType() != Cue::CUE || pCue->getHotCue() == -1) { continue; } int cue_position = pCue->getPosition(); //pick cues closest to new_playpos if ((nearest_playpos == -1) || (fabs(new_playpos - cue_position) < distance)) { nearest_playpos = cue_position; distance = fabs(new_playpos - cue_position); } } if (nearest_playpos == -1) { if (new_playpos >= 0) { //never found an appropriate cue, so don't seek? return; } //if negative, allow a seek by falling down to the bottom } else { m_bSeekRequested = true; seekExact(nearest_playpos); m_bSeekRequested = false; return; } } // Just seek where it wanted to originally. m_bSeekRequested = true; seek(change); m_bSeekRequested = false; }