/*************************************** * startSendingAudio * Helper function ***************************************/ void * AudioStream::startSendingAudio(void *par) { AudioStream *conf = (AudioStream *)par; blocksignals(); Log("SendAudioThread [%d]\n",getpid()); pthread_exit((void *)conf->SendAudio()); }
/*************************************** * startReceivingAudio * Helper function ***************************************/ void * AudioStream::startReceivingAudio(void *par) { AudioStream *conf = (AudioStream *)par; blocksignals(); Log("RecvAudioThread [%d]\n",getpid()); pthread_exit((void *)conf->RecAudio()); }
AAUDIO_API aaudio_result_t AAudioStream_write(AAudioStream* stream, const void *buffer, int32_t numFrames, int64_t timeoutNanoseconds) { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); if (buffer == nullptr) { return AAUDIO_ERROR_NULL; } // Don't allow writes when playing with a callback. if (audioStream->getDataCallbackProc() != nullptr && audioStream->isActive()) { ALOGE("Cannot write to a callback stream when running."); return AAUDIO_ERROR_INVALID_STATE; } if (numFrames < 0) { return AAUDIO_ERROR_ILLEGAL_ARGUMENT; } else if (numFrames == 0) { return 0; } aaudio_result_t result = audioStream->write(buffer, numFrames, timeoutNanoseconds); return result; }
// Timer callback for Timer object created by ::Play method. BOOL AudioStream::TimerCallback (DWORD dwUser) { // dwUser contains ptr to AudioStream object AudioStream * pas = (AudioStream *) dwUser; return (pas->ServiceBuffer ()); }
bool SynthRoute::pushMIDISysex(const Bit8u *sysexData, unsigned int sysexLen, MasterClockNanos refNanos) { recorder.recordSysex(sysexData, sysexLen, refNanos); AudioStream *stream = audioStream; if (stream == NULL) return false; quint64 timestamp = stream->estimateMIDITimestamp(refNanos); return qSynth.playMIDISysex(sysexData, sysexLen, timestamp); }
virtual int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) { assert(input.isStereo() == stereo); #ifdef DEBUG_RATECONV debug("Copy st=%d rev=%d", stereo, reverseStereo); #endif st_size_t len; st_sample_t *ostart = obuf; if (stereo) osamp *= 2; // Reallocate temp buffer, if necessary if (osamp > _bufferSize) { free(_buffer); _buffer = (st_sample_t *)malloc(osamp * 2); _bufferSize = osamp; } // Read up to 'osamp' samples into our temporary buffer len = input.readBuffer(_buffer, osamp); if (len <= 0) return 0; // Mix the data into the output buffer if (stereo && reverseStereo) obuf = ARM_CopyRate_R(len, obuf, vol_l, vol_r, _buffer); else if (stereo) obuf = ARM_CopyRate_S(len, obuf, vol_l, vol_r, _buffer); else obuf = ARM_CopyRate_M(len, obuf, vol_l, vol_r, _buffer); return (obuf-ostart)/2; }
size_t ASFStream::readBuffer(int16 *buffer, const size_t numSamples) { size_t samplesDecoded = 0; for (;;) { if (_curAudioStream) { const size_t n = _curAudioStream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); if (n == kSizeInvalid) return kSizeInvalid; samplesDecoded += n; if (_curAudioStream->endOfData()) { delete _curAudioStream; _curAudioStream = 0; } } if (samplesDecoded == numSamples || endOfData()) break; if (!_curAudioStream) { _curAudioStream = createAudioStream(); } } return samplesDecoded; }
AAUDIO_API aaudio_result_t AAudioStream_requestStart(AAudioStream* stream) { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); ALOGD("AAudioStream_requestStart(%p) called --------------", stream); aaudio_result_t result = audioStream->systemStart(); ALOGD("AAudioStream_requestStart(%p) returned %d ---------", stream, result); return result; }
AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream, aaudio_stream_state_t inputState, aaudio_stream_state_t *nextState, int64_t timeoutNanoseconds) { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds); }
void AudioManager::stop_stream(int stream_idx) { if (stream_idx < 0) return; AudioStream *strm = get_audio_stream(stream_idx); if (strm && strm->is_playing()) strm->stop(); }
AAUDIO_API aaudio_result_t AAudioStream_close(AAudioStream* stream) { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); ALOGD("AAudioStream_close(%p)", stream); if (audioStream != nullptr) { audioStream->close(); audioStream->unregisterPlayerBase(); delete audioStream; return AAUDIO_OK; } return AAUDIO_ERROR_NULL; }
AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream, clockid_t clockid, int64_t *framePosition, int64_t *timeNanoseconds) { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); if (framePosition == nullptr) { return AAUDIO_ERROR_NULL; } else if (timeNanoseconds == nullptr) { return AAUDIO_ERROR_NULL; } else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) { return AAUDIO_ERROR_ILLEGAL_ARGUMENT; } return audioStream->getTimestamp(clockid, framePosition, timeNanoseconds); }
void Laboratory::checkAndSave(TrialsSet& trialsSet, AudioStream& audioStream, InputAudioParameters& str, CheckMethodType checkMethod, std::string folderForAudioResults ) { //Check - write result to file if(str.data_source == AudioStream::AUDIO_FILE_AS_SOURCE) { audioStream.close (resultsPath_ + folderForAudioResults + std::string("/") + str.outFileName, true); audioStream.cutAndClose (resultsPath_ + folderForAudioResults + std::string("/") + std::string("cutted__") +str.outFileName, trialsSet, false ); } if(str.data_source == AudioStream::RANDOM_DATA_AS_SOURCE) if(checkMethod == CheckMethodType::ifOutSilence) if(audioStream.checkIfOutSilence()) throw UnkownInternalProcessingError_Exception(); if(checkMethod == CheckMethodType::ifTheInTheSameAsOut) if(!audioStream.checkIfOutTheSameAsIn()) throw UnkownInternalProcessingError_Exception(); //. }
int QueuingAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock lock(_mutex); int samplesDecoded = 0; while (samplesDecoded < numSamples && !_queue.empty()) { AudioStream *stream = _queue.front()._stream; samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); if (stream->endOfData()) { StreamHolder tmp = _queue.pop(); if (tmp._disposeAfterUse == DisposeAfterUse::YES) delete stream; } } return samplesDecoded; }
bool SynthRoute::pushMIDIShortMessage(Bit32u msg, MasterClockNanos refNanos) { recorder.recordShortMessage(msg, refNanos); AudioStream *stream = audioStream; if (stream == NULL) return false; quint64 timestamp = stream->estimateMIDITimestamp(refNanos); if (msg == 0) { // This is a special event sent by the test driver qint64 delta = qint64(timestamp - debugLastEventTimestamp); MasterClockNanos debugEventNanoOffset = (refNanos == 0) ? 0 : MasterClock::getClockNanos() - refNanos; if ((delta < debugDeltaLowerLimit) || (debugDeltaUpperLimit < delta) || ((15 * MasterClock::NANOS_PER_MILLISECOND) < debugEventNanoOffset)) { qDebug() << "M" << delta << timestamp << 1e-6 * debugEventNanoOffset; } debugLastEventTimestamp = timestamp; return false; } return qSynth.playMIDIShortMessage(msg, timestamp); }
AAUDIO_API aaudio_result_t AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder, AAudioStream** streamPtr) { AudioStream *audioStream = nullptr; // Please leave these logs because they are very helpful when debugging. ALOGD("AAudioStreamBuilder_openStream() called ----------------------------------------"); AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr); aaudio_result_t result = streamBuilder->build(&audioStream); ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------", result, AAudio_convertResultToText(result), audioStream); if (result == AAUDIO_OK) { audioStream->registerPlayerBase(); *streamPtr = (AAudioStream*) audioStream; } else { *streamPtr = nullptr; } return result; }
AAUDIO_API aaudio_result_t AAudioStream_read(AAudioStream* stream, void *buffer, int32_t numFrames, int64_t timeoutNanoseconds) { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); if (buffer == nullptr) { return AAUDIO_ERROR_NULL; } if (numFrames < 0) { return AAUDIO_ERROR_ILLEGAL_ARGUMENT; } else if (numFrames == 0) { return 0; } aaudio_result_t result = audioStream->read(buffer, numFrames, timeoutNanoseconds); return result; }
/* ================ AudioStream::Open ================ */ AudioStream *AudioStream::Open( const char *filename ) { String extension = String::GetFileExtension( filename, String::Length(filename) ); AudioStream *stream; if ( extension.Icmp("ogg") == 0 ) stream = new VorbisStream; else if ( extension.Icmp("wav") == 0 ) stream = new WavStream; else { //common->Warning("Unknown extension '%s'", extension.c_str() ); return OG_NULL; } if ( !stream->LoadFile( filename ) ) { delete stream; return OG_NULL; } return stream; }
// When a map is selected in the song wheel void OnMapSelected(MapIndex* map) { if(map == m_currentPreviewAudio) return; // Set current preview audio DifficultyIndex* previewDiff = map->difficulties[0]; String audioPath = map->path + Path::sep + previewDiff->settings.audioNoFX; AudioStream previewAudio = g_audio->CreateStream(audioPath); if(previewAudio) { previewAudio->SetPosition(previewDiff->settings.previewOffset); m_previewPlayer.FadeTo(previewAudio); } else { Logf("Failed to load preview audio from [%s]", Logger::Warning, audioPath); m_previewPlayer.FadeTo(AudioStream()); } m_currentPreviewAudio = map; }
int QueuingAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock lock(_mutex); int samplesDecoded = 0; while (samplesDecoded < numSamples && !_queue.empty()) { AudioStream *stream = _queue.front()._stream; samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); // Done with the stream completely if (stream->endOfStream()) { StreamHolder tmp = _queue.pop(); if (tmp._disposeAfterUse == DisposeAfterUse::YES) delete stream; continue; } // Done with data but not the stream, bail out if (stream->endOfData()) break; } return samplesDecoded; }
size_t QueuingAudioStreamImpl::readBuffer(int16 *buffer, const size_t numSamples) { Common::StackLock lock(_mutex); size_t samplesDecoded = 0; while (samplesDecoded < numSamples && !_queue.empty()) { AudioStream *stream = _queue.front()._stream; const size_t n = stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); if (n == kSizeInvalid) return kSizeInvalid; samplesDecoded += n; if (stream->endOfData()) { StreamHolder tmp = _queue.front(); _queue.pop(); if (tmp._disposeAfterUse) delete stream; } } return samplesDecoded; }
int ASFStream::readBuffer(int16 *buffer, const int numSamples) { int samplesDecoded = 0; for (;;) { if (_curAudioStream) { samplesDecoded += _curAudioStream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); if (_curAudioStream->endOfData()) { delete _curAudioStream; _curAudioStream = 0; } } if (samplesDecoded == numSamples || endOfData()) break; if (!_curAudioStream) { _curAudioStream = createAudioStream(); } } return samplesDecoded; }
bool AlsaSource::InitializeAlsa () { bool res = false; int result; AudioStream *stream = NULL; LOG_AUDIO ("AlsaSource::InitializeAlsa (%p) initialized: %i\n", this, initialized); mutex.Lock (); if (initialized) { result = true; goto cleanup; } stream = GetStreamReffed (); if (stream == NULL) { // Shouldn't really happen, but handle this case anyway. LOG_AUDIO ("AlsaSource::Initialize (): trying to initialize an audio device, but there's no audio to play.\n"); goto cleanup; } // Open a pcm device result = snd_pcm_open (&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0 /*SND_PCM_NONBLOCK*/); if (result != 0) { LOG_AUDIO ("AlsaSource::Initialize (): cannot open audio device: %s\n", snd_strerror (result)); pcm = NULL; goto cleanup; } // Configure the hardware if (!SetupHW ()) { LOG_AUDIO ("AlsaSource::Initialize (): could not configure hardware for audio playback\n"); Close (); goto cleanup; } result = snd_pcm_get_params (pcm, &buffer_size, &period_size); if (result != 0) { LOG_AUDIO ("AlsaSource::Initialize (): error while getting parameters: %s\n", snd_strerror (result)); Close (); goto cleanup; } // Get the file descriptors to poll on ndfs = snd_pcm_poll_descriptors_count (pcm); if (ndfs <= 0) { LOG_AUDIO ("AlsaSource::Initialize(): Unable to initialize audio for playback (could not get poll descriptor count).\n"); Close (); goto cleanup; } udfs = (pollfd *) g_malloc0 (sizeof (pollfd) * ndfs); if (snd_pcm_poll_descriptors (pcm, udfs, ndfs) < 0) { LOG_AUDIO ("AlsaSource::Initialize (): Unable to initialize audio for playback (could not get poll descriptors).\n"); Close (); goto cleanup; } LOG_AUDIO ("AlsaSource::Initialize (%p): Succeeded. Buffer size: %lu, period size: %lu\n", this, buffer_size, period_size); res = true; initialized = true; cleanup: mutex.Unlock (); if (stream) stream->unref (); return res; }
void meWatchFun() { const float fadeOutStep = 1.f / (200 / AUDIO_SLEEP); const float fadeInStep = 1.f / (1000 / AUDIO_SLEEP); while (true) { syncPoint.passSecondarySync(); if (meWatch.termReq) return; switch (meWatch.state) { case MeNotPlaying: { me.lockStream(); if (me.stream.queryState() == ALStream::Playing) { /* ME playing detected. -> FadeOutBGM */ bgm.extPaused = true; meWatch.state = BgmFadingOut; } me.unlockStream(); break; } case BgmFadingOut : { me.lockStream(); if (me.stream.queryState() != ALStream::Playing) { /* ME has ended while fading OUT BGM. -> FadeInBGM */ me.unlockStream(); meWatch.state = BgmFadingIn; break; } bgm.lockStream(); float vol = bgm.getVolume(AudioStream::External); vol -= fadeOutStep; if (vol < 0 || bgm.stream.queryState() != ALStream::Playing) { /* Either BGM has fully faded out, or stopped midway. -> MePlaying */ bgm.setVolume(AudioStream::External, 0); bgm.stream.pause(); meWatch.state = MePlaying; bgm.unlockStream(); me.unlockStream(); break; } bgm.setVolume(AudioStream::External, vol); bgm.unlockStream(); me.unlockStream(); break; } case MePlaying : { me.lockStream(); if (me.stream.queryState() != ALStream::Playing) { /* ME has ended */ bgm.lockStream(); bgm.extPaused = false; ALStream::State sState = bgm.stream.queryState(); if (sState == ALStream::Paused) { /* BGM is paused. -> FadeInBGM */ bgm.stream.play(); meWatch.state = BgmFadingIn; } else { /* BGM is stopped. -> MeNotPlaying */ bgm.setVolume(AudioStream::External, 1.0); if (!bgm.noResumeStop) bgm.stream.play(); meWatch.state = MeNotPlaying; } bgm.unlockStream(); } me.unlockStream(); break; } case BgmFadingIn : { bgm.lockStream(); if (bgm.stream.queryState() == ALStream::Stopped) { /* BGM stopped midway fade in. -> MeNotPlaying */ bgm.setVolume(AudioStream::External, 1.0); meWatch.state = MeNotPlaying; bgm.unlockStream(); break; } me.lockStream(); if (me.stream.queryState() == ALStream::Playing) { /* ME started playing midway BGM fade in. -> FadeOutBGM */ bgm.extPaused = true; meWatch.state = BgmFadingOut; me.unlockStream(); bgm.unlockStream(); break; } float vol = bgm.getVolume(AudioStream::External); vol += fadeInStep; if (vol >= 1) { /* BGM fully faded in. -> MeNotPlaying */ vol = 1.0; meWatch.state = MeNotPlaying; } bgm.setVolume(AudioStream::External, vol); me.unlockStream(); bgm.unlockStream(); break; } } SDL_Delay(AUDIO_SLEEP); } }
int main(int argc, char *argv[]) { init(argc, argv); AudioFile a(input1.c_str()); AudioFile b(input2.c_str()); if (channel >= a.getNumberOfChannels() || channel >= b.getNumberOfChannels()) { ls << log_error() << "Error, channel not available" << endl; return 1; } //cross correlate x seconds at a time. uint32_t samplesPrBlock = a.getSampleRate() * secondsPrBlock; ls << log_debug() << "samples a: " << samplesPrBlock << endl; ls << log_debug() << "samples b: " << b.getSampleRate() * secondsPrBlock << endl; AudioStream aStream = a.getStream(channel); AudioStream bStream = b.getStream(channel); bool done = false; bool first = true; bool success = true; size_t blockFailure = 0; double blockFailureVal = 0.0; int64_t blockFailureOffset = 0; double firstMaxVal = 0.0; int64_t firstOffset = 0; double minimumVal = 2; for (size_t block = 1; !done; ++block) { vector<int16_t> aSamples, bSamples; vector<uint64_t> aSquarePrefixSum, bSquarePrefixSum; vector<complex<double> > result; aStream.read(samplesPrBlock, aSamples); bStream.read(samplesPrBlock, bSamples); if (aSamples.size() == 0 && bSamples.size() == 0) { // reached the end of both of the samples if (verbose) { cout << "finished: reached end of both samples" << endl; } break; } if (padShortBlock) { // If this correlation involves 'short' files, shorter than one // block, pad the blocks with silence - this will only pad the last // block, so that for short files, shorter than one block, the // correlation is performed, rather than terminating the loop early // in the following break, leaving minimumVal as 2, and indicating // success. Because we're looping until the end of both samples, // this will pad out a shorter sample with silence (which will // probably yield a correlation failure) aSamples.resize(samplesPrBlock, 0); bSamples.resize(samplesPrBlock, 0); } if (aSamples.size() < samplesPrBlock/2 || bSamples.size() < samplesPrBlock) { // not enough samples for another reliable check. if (verbose) { cout << "finished: not enough samples for another reliable check" << endl; } break; } prefixSquareSum(aSamples, aSquarePrefixSum); prefixSquareSum(bSamples, bSquarePrefixSum); // we count the average of absolute values // if the average is close to 0, then we decide it is silence size_t absSumA = 0; size_t absSumB = 0; bool silence = false; for (size_t i = 0; i < aSamples.size(); ++i) { absSumA += (aSamples[i]>=0)?aSamples[i]:-aSamples[i]; } for (size_t i = 0; i < bSamples.size(); ++i) { absSumB += (bSamples[i]>=0)?bSamples[i]:-bSamples[i]; } double avgA = static_cast<double>(absSumA)/aSamples.size(); double avgB = static_cast<double>(absSumB)/bSamples.size(); if (avgA <= 5.0 && avgB <= 5.0) { silence = true; } else if (avgA <= 5.0 || avgB <= 5.0) { success = false; } bool compare = !silence; int64_t maxIdx = -1; double maxVal = -1.0; if (compare) { proxyFFT<int16_t, double> aFFT(aSamples); proxyFFT<int16_t, double> bFFT(bSamples); pair<int64_t, double> tmp = compareBlock(aFFT, bFFT, aSquarePrefixSum, bSquarePrefixSum); maxIdx = tmp.first; maxVal = tmp.second; tmp = compareBlock(bFFT, aFFT, bSquarePrefixSum, aSquarePrefixSum); if (tmp.second > maxVal + 1e-6) { maxIdx = -tmp.first; maxVal = tmp.second; } if (first) { first = false; firstMaxVal = maxVal; firstOffset = maxIdx; minimumVal = maxVal; if (firstMaxVal < threshold) { if (verbose) { cout << "failed: threshold crossed in first block (" << firstMaxVal << ")" << endl; } success = false; blockFailure = block; blockFailureVal = maxVal; blockFailureOffset = maxIdx; } } else { int64_t offsetDistance = abs(maxIdx - firstOffset); bool offsetDistanceExceeded = offsetDistance > 500; bool thresholdCrossed = maxVal < threshold; if (offsetDistanceExceeded || thresholdCrossed) { if (verbose && offsetDistanceExceeded) { cout << "failed: offset distance exceeded (" << offsetDistance << ")" << endl; } if (verbose && thresholdCrossed) { cout << "failed: threshold crossed (" << maxVal << ")" << endl; } // check to see that the offset between blocks is not too large. success = false; blockFailure = block; blockFailureVal = maxVal; blockFailureOffset = maxIdx; } if (maxVal < minimumVal) { minimumVal = maxVal; } } } if (aSamples.size() < samplesPrBlock || bSamples.size() < samplesPrBlock) { // we don't check the last block. Is this ok? if (verbose) { cout << "finished: at last block" << endl; } done = true; } if (verbose) { if (compare) { cout << "block " << block << ": " << maxVal << " " << maxIdx << endl; } else if (silence) { cout << "block " << block << ": " << "silence" << endl; } } } if (success) { cout << "Success" << endl; cout << "Offset: " << firstOffset << endl; cout << "Similarity: " << minimumVal << endl; return 0; } else { cout << "Failure" << endl; cout << "Block: " << blockFailure << endl; cout << "Value in block: " << blockFailureVal << endl; cout << "Offset in block: " << blockFailureOffset << " (normal: " << firstOffset << ")" << endl; return 1; /* cout << "block " << blockFailure << ":" << endl; cout << "Time: " << getTimestampFromSeconds(blockFailure*5-5) << " - " << getTimestampFromSeconds(blockFailure*5) << " did not match properly" << endl; */ } }
/** * The playback thread code * \internal */ void *narrator_thread(void *narrator) { //Narrator *n = static_cast<Narrator *>(narrator); Narrator *n = (Narrator*)narrator; int queueitems; // Set initial values to 0 so that they get updated when thread gets play signal float gain = 0; float tempo = 0; float pitch = 0; PortAudio portaudio; Filter filter; Narrator::threadState state = n->getState(); LOG4CXX_INFO(narratorLog, "Starting playback thread"); do { queueitems = n->numPlaylistItems(); if(queueitems == 0) { // Wait a little before calling callback long waitms = portaudio.getRemainingms(); if(waitms != 0) { LOG4CXX_DEBUG(narratorLog, "Waiting " << waitms << " ms for playback to finish"); while(waitms > 0 && queueitems == 0) { usleep(100000); queueitems = n->numPlaylistItems(); waitms -= 100; } } // Break if we during the pause got some more queued items to play if(queueitems == 0) { if(state != Narrator::DEAD) n->audioFinishedPlaying(); n->setState(Narrator::WAIT); LOG4CXX_INFO(narratorLog, "Narrator in WAIT state"); portaudio.stop(); while(queueitems == 0) { state = n->getState(); if(state == Narrator::EXIT) break; usleep(10000); queueitems = n->numPlaylistItems(); } } LOG4CXX_INFO(narratorLog, "Narrator starting playback"); } if(state == Narrator::EXIT) break; n->setState(Narrator::PLAY); n->bResetFlag = false; Narrator::PlaylistItem pi; pthread_mutex_lock(n->narratorMutex); if(n->mPlaylist.size() > 0) { pi = n->mPlaylist.front(); n->mPlaylist.pop(); } else { LOG4CXX_ERROR(narratorLog, "Narrator started playback thread without playlistitems"); pthread_mutex_unlock(n->narratorMutex); continue; } string lang = n->mLanguage; pthread_mutex_unlock(n->narratorMutex); // If trying to play a file, open it if(pi.mClass == "file") { LOG4CXX_DEBUG(narratorLog, "Playing file: " << pi.mIdentifier); AudioStream *audioStream; std::string fileExtension = getFileExtension(pi.mIdentifier); if (fileExtension == "ogg") { audioStream = new OggStream; } else if (fileExtension == "mp3") { audioStream = new Mp3Stream; } else { LOG4CXX_ERROR(narratorLog, "extension '" << fileExtension << "' not supported"); continue; } if(!audioStream->open(pi.mIdentifier)) { LOG4CXX_ERROR(narratorLog, "error opening audio stream: " << pi.mIdentifier); audioStream->close(); continue; } if (portaudio.getRate() != audioStream->getRate()) { long waitms = portaudio.getRemainingms(); if (waitms != 0) { LOG4CXX_DEBUG(narratorLog, "Waiting for current playback to finish"); while (waitms > 0) { usleep(100000); waitms -= 100; } } } if(!portaudio.open(audioStream->getRate(), audioStream->getChannels())) { LOG4CXX_ERROR(narratorLog, "error initializing portaudio, (rate: " << audioStream->getRate() << " channels: " << audioStream->getChannels() << ")"); continue; } if(!filter.open(audioStream->getRate(), audioStream->getChannels())) { LOG4CXX_ERROR(narratorLog, "error initializing filter"); continue; } LOG4CXX_DEBUG(narratorLog, "Audio stream has " << audioStream->getChannels() << " channel(s) and rate " << audioStream->getRate() << " Hz"); int inSamples = 0; soundtouch::SAMPLETYPE* buffer = new soundtouch::SAMPLETYPE[audioStream->getChannels()*BUFFERSIZE]; //buffer = (short*)malloc(sizeof(short) * 2 * BUFFERSIZE); // long totalSamplesRead = 0; do { // change gain, tempo and pitch adjustGainTempoPitch(n, filter, gain, tempo, pitch); // read some stuff from the audio stream inSamples = audioStream->read(buffer, BUFFERSIZE/**audioStream->getChannels()*/); LOG4CXX_TRACE(narratorLog, "got " << inSamples << " samples"); //printf("Read %d samples from audio stream\n", inSamples); if(inSamples != 0) { filter.write(buffer, inSamples); // One sample contains data for all channels here writeSamplesToPortaudio( n, portaudio, filter, buffer ); } else { LOG4CXX_INFO(narratorLog, "Flushing soundtouch buffer"); filter.flush(); } state = n->getState(); } while (inSamples != 0 && state == Narrator::PLAY && !n->bResetFlag); if(buffer != NULL) delete [] (buffer); audioStream->close(); delete audioStream; } // Else try opening from database else { vector <MessageAudio> vAudioQueue; // Get a list of MessageAudio objects to play Message *m = pi.mMessage; if(m==NULL){ LOG4CXX_ERROR(narratorLog, "Message was null"); } m->setLanguage(lang); m->load(pi.mIdentifier, pi.mClass); if(!m->compile() || !m->hasAudio()) { LOG4CXX_ERROR(narratorLog, "Narrator translation not found: could not find audio for '" << pi.mIdentifier << "'"); } else { vAudioQueue = m->getAudioQueue(); } // Play what we got if(vAudioQueue.size() > 0) { vector <MessageAudio>::iterator audio; audio = vAudioQueue.begin(); do { LOG4CXX_INFO(narratorLog, "Saying: " << audio->getText()); AudioStream *audioStream; std::string encoding = ((MessageAudio&)*audio).getEncoding(); if (encoding == "ogg") { audioStream = new OggStream; } else if (encoding == "mp3") { audioStream = new Mp3Stream; } else { LOG4CXX_ERROR(narratorLog, "encoding '" << encoding << "' not supported"); audio++; continue; } if(!audioStream->open(*audio)) { LOG4CXX_ERROR(narratorLog, "error opening audio stream"); audioStream->close(); break; } if (portaudio.getRate() != audioStream->getRate()) { long waitms = portaudio.getRemainingms(); if (waitms != 0) { LOG4CXX_DEBUG(narratorLog, "Waiting for current playback to finish"); while (waitms > 0) { usleep(100000); waitms -= 100; } } } if(!portaudio.open(audioStream->getRate(), audioStream->getChannels())) { LOG4CXX_ERROR(narratorLog, "error initializing portaudio"); break; } if(!filter.open(audioStream->getRate(), audioStream->getChannels())) { LOG4CXX_ERROR(narratorLog, "error initializing filter"); break; } int inSamples = 0; soundtouch::SAMPLETYPE* buffer = new soundtouch::SAMPLETYPE[audioStream->getChannels()*BUFFERSIZE]; do { // change gain, tempo and pitch adjustGainTempoPitch(n, filter, gain, tempo, pitch); // read some stuff from the audio stream inSamples = audioStream->read(buffer, BUFFERSIZE*audioStream->getChannels()); if(inSamples != 0) { filter.write(buffer, inSamples); writeSamplesToPortaudio( n, portaudio, filter, buffer ); } else { LOG4CXX_INFO(narratorLog, "Flushing soundtouch buffer"); filter.flush(); } state = n->getState(); } while (inSamples != 0 && state == Narrator::PLAY && !n->bResetFlag); if(buffer != NULL) delete [] (buffer); audioStream->close(); audio++; } while(audio != vAudioQueue.end() && state == Narrator::PLAY && !n->bResetFlag); } //Cleanup message object delete(pi.mMessage); } // Abort stream? if(n->bResetFlag) { n->bResetFlag = false; portaudio.stop(); filter.clear(); } } while(state != Narrator::EXIT); LOG4CXX_INFO(narratorLog, "Shutting down playbackthread"); pthread_exit(NULL); return NULL; }
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; }
void match(AudioFile &needle, AudioFile &haystack, std::vector<pair<size_t, double> > &results) { std::vector<short> small; std::vector<short> large; std::vector<int64_t> smallPrefixSum; std::vector<int64_t> largePrefixSum; needle.getSamplesForChannel(0, small); prefixSquareSum(small, smallPrefixSum); proxyFFT<short, double> smallFFT(small); smallFFT.transform(); size_t largeTotalSize = haystack.getNumberOfSamplesPrChannel(); // vector<int64_t> maxSamplesBegin(largeTotalSize/small.size()); // vector<int64_t> maxSamplesEnd(largeTotalSize/small.size()); vector<Record> maxSamplesBegin(largeTotalSize/small.size()); vector<Record> maxSamplesEnd(largeTotalSize/small.size()); size_t stillToRead = largeTotalSize; AudioStream hayStream = haystack.getStream(0); size_t pieces = 13; for (int j = 0; ; ++j) { hayStream.read(pieces*small.size(), large); prefixSquareSum(large, largePrefixSum); size_t numberOfParts = large.size()/small.size(); size_t idxAdd = j*pieces; // Progress information std::cout << '\r' << setw(8) << ((largeTotalSize-stillToRead)+0.0)/largeTotalSize*100 << " %"; std::cout.flush(); stillToRead -= large.size(); for (size_t ii = 0; ii < numberOfParts*small.size(); ii += small.size()) { //do stuff.. proxyFFT<short, double> largeFFT(large.begin()+ii, large.begin()+ii+small.size()); vector<complex<double> > outBegin; vector<complex<double> > outEnd; //std::cout << "TEST1" << std::endl; cross_correlation(largeFFT, smallFFT, outBegin); cross_correlation(smallFFT, largeFFT, outEnd); size_t maxSampleBegin = 0; double maxNormFactorBegin = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin(), smallPrefixSum.end(), largePrefixSum.begin()+ii, largePrefixSum.begin()+small.size()+ii); for (size_t i = 0 ; i < outBegin.size(); ++i) { double normFactor = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin(), smallPrefixSum.end()-i, largePrefixSum.begin()+i+ii, largePrefixSum.begin()+ii+small.size()); if (outBegin[maxSampleBegin].real()/maxNormFactorBegin < outBegin[i].real()/normFactor) { maxSampleBegin = i; maxNormFactorBegin = normFactor; } } //std::cout << "TEST2" << std::endl; size_t maxSampleEnd = 0; double maxNormFactorEnd = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin(), smallPrefixSum.end(), largePrefixSum.begin()+ii, largePrefixSum.begin()+small.size()+ii); for (size_t i = 0 ; i < outEnd.size(); ++i) { double normFactor = computeNormFactor(smallPrefixSum, largePrefixSum, smallPrefixSum.begin()+i, smallPrefixSum.end(), largePrefixSum.begin()+ii, largePrefixSum.begin()-i+ii+small.size()); if (outEnd[maxSampleEnd].real()/maxNormFactorEnd < outEnd[i].real()/normFactor) { maxSampleEnd = i; maxNormFactorEnd = normFactor; } } maxSamplesBegin[ii/small.size()+idxAdd] = Record(maxNormFactorBegin, outBegin[maxSampleBegin].real(), small.size() - maxSampleBegin); maxSamplesEnd[ii/small.size()+idxAdd] = Record(maxNormFactorEnd, outEnd[maxSampleEnd].real(), small.size() - maxSampleEnd); } if (numberOfParts != pieces) break; } std::cout << '\r' << setw(8) << 100 << "%" << std::endl; // // FIXME: special case. // // small size does not divide large size // // => last piece is not analysed. // // fix this. for (size_t i = 0; i < maxSamplesBegin.size()-1; ++i) { double val = (maxSamplesBegin[i].cv + maxSamplesEnd[i+1].cv)/(maxSamplesBegin[i].nf + maxSamplesEnd[i+1].nf); if (val > 0.3) { // arbitrary magic number. Seems to work well. size_t length = maxSamplesBegin[i].s + maxSamplesEnd[i+1].s; if (length <= small.size() && length >= THRESHHOLD*small.size()) { // length must be appropriate results.push_back(make_pair((i+1)*small.size()-maxSamplesBegin[i].s, val)); } } } }
AUDIOAPI AudioStream MakeReturn(AudioStream send_stream) { if(auto send = dynamic_cast<TSendAudioStream*>(send_stream.getPointer())) return new TReturnAudioStream{send}; return nullptr; }
void Laboratory::addStandardAndStatisticsProperties(TrialsSet& trialsSet, AudioStream& audioStream, InputAudioParameters& str ) { trialsSet.properties_.add( Properties::lengthInSeconds, (unsigned int) ceil(((double)str.blockSize*trialsSet.get_trialsNumber())/((double)audioStream.get_sampleRate())) ); trialsSet.properties_.add( Properties::repetition, (unsigned int) trialsSet.get_trialsNumber() ); trialsSet.properties_.add( Properties::block_size, (unsigned int) str.blockSize ); trialsSet.properties_.add( Properties::sample_rate, (unsigned int) audioStream.get_sampleRate() ); trialsSet.properties_.add( Properties::latency, (double) (double)str.blockSize/(double)audioStream.get_sampleRate()*(double)1000 ); trialsSet.properties_.add( Properties::num_of_channels, (unsigned int) audioStream.get_numOfChannels() ); //--- StatisticsComputator::compute(trialsSet); //--- }