void eladWorker:: run (void) { int32_t amount; int rc; // // we build in a delay such that it can be expected that the // data is in place. We read app 100 times a second a buffer // per read we have BUFFERSIZE / 8 samples, so we wait fprintf (stderr, "New elad-worker\n"); while (runnable) { rc = libusb_bulk_transfer (functions -> getHandle (), (6 | LIBUSB_ENDPOINT_IN), (uint8_t *)buffer, BUFFER_SIZE * sizeof (int8_t), &amount, 2000); if (rc) { fprintf (stderr, "Error in libusb_bulk_transfer: [%d] %s\n", rc, libusb_error_name (rc)); if (rc != 7) break; } _I_Buffer -> putDataIntoBuffer (buffer, amount); usleep (20); if (_I_Buffer -> GetRingBufferReadAvailable () > theRate / 10) emit samplesAvailable (theRate / 10); } fprintf (stderr, "eladWorker now stopped\n"); }
bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const { if (!_isStarved) { return true; } else { return samplesAvailable() >= numRequiredSamples; } }
bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { if (!isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + numJitterBufferSamples)) { if (_shouldOutputStarveDebug) { _shouldOutputStarveDebug = false; } return false; } else if (samplesAvailable() < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { _isStarved = true; // reset our _shouldOutputStarveDebug to true so the next is printed _shouldOutputStarveDebug = true; return false; } else { // good buffer, add this to the mix _isStarved = false; // since we've read data from ring buffer at least once - we've started _hasStarted = true; return true; } return false; }
int AudioRingBuffer::writeData(const char* data, int maxSize) { // make sure we have enough bytes left for this to be the right amount of audio // otherwise we should not copy that data, and leave the buffer pointers where they are int samplesToCopy = std::min((int)(maxSize / sizeof(int16_t)), _sampleCapacity); int samplesRoomFor = _sampleCapacity - samplesAvailable(); if (samplesToCopy > samplesRoomFor) { // there's not enough room for this write. erase old data to make room for this new data int samplesToDelete = samplesToCopy - samplesRoomFor; _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); _overflowCount++; qCDebug(audio) << "Overflowed ring buffer! Overwriting old data"; } if (_endOfLastWrite + samplesToCopy <= _buffer + _bufferLength) { memcpy(_endOfLastWrite, data, samplesToCopy * sizeof(int16_t)); } else { int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite; memcpy(_endOfLastWrite, data, numSamplesToEnd * sizeof(int16_t)); memcpy(_buffer, data + (numSamplesToEnd * sizeof(int16_t)), (samplesToCopy - numSamplesToEnd) * sizeof(int16_t)); } _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, samplesToCopy); return samplesToCopy * sizeof(int16_t); }
bool DsfFileReader::readNextBlock() { // return false if this is the end of the file if (!samplesAvailable()) { // fill the blockBuffer with the idle sample dsf2flac_uint8 idle = getIdleSample(); for (dsf2flac_uint32 i=0; i<chanNum; i++) for (dsf2flac_uint32 j=0; j<blockSzPerChan; j++) blockBuffer[i][j] = idle; return false; } for (dsf2flac_uint32 i=0; i<chanNum; i++) { if (file.read_uint8(blockBuffer[i],blockSzPerChan)) { // if read failed fill the blockBuffer with the idle sample dsf2flac_uint8 idle = getIdleSample(); for (dsf2flac_uint32 i=0; i<chanNum; i++) for (dsf2flac_uint32 j=0; j<blockSzPerChan; j++) blockBuffer[i][j] = idle; return false; } } blockCounter++; blockMarker=0; return true; }
int AudioRingBuffer::writeSamplesWithFade(ConstIterator source, int maxSamples, float fade) { int samplesToCopy = std::min(maxSamples, _sampleCapacity); int samplesRoomFor = _sampleCapacity - samplesAvailable(); if (samplesToCopy > samplesRoomFor) { // there's not enough room for this write. erase old data to make room for this new data int samplesToDelete = samplesToCopy - samplesRoomFor; _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); _overflowCount++; qCDebug(audio) << "Overflowed ring buffer! Overwriting old data"; } int16_t* bufferLast = _buffer + _bufferLength - 1; for (int i = 0; i < samplesToCopy; i++) { *_endOfLastWrite = (int16_t)((float)(*source) * fade); _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; ++source; } return samplesToCopy; }
bool DsdiffFileReader::step() { bool ok = true; if (!samplesAvailable()) ok = false; else if (bufferMarker>=sampleBufferLenPerChan) ok = readNextBlock(); if (ok) { for (dsf2flac_uint16 i=0; i<chanNum; i++) circularBuffers[i].push_front(sampleBuffer[i+bufferMarker*chanNum]); bufferMarker++; } else { for (dsf2flac_uint16 i=0; i<chanNum; i++) circularBuffers[i].push_front(getIdleSample()); } posMarker++; return ok; }
bool DsfFileReader::step() { bool ok = true; if (!samplesAvailable()) ok = false; else if (blockMarker>=blockSzPerChan) ok = readNextBlock(); if (ok) { for (dsf2flac_uint32 i=0; i<chanNum; i++) circularBuffers[i].push_front(blockBuffer[i][blockMarker]); blockMarker++; } else { for (dsf2flac_uint32 i=0; i<chanNum; i++) circularBuffers[i].push_front(getIdleSample()); } posMarker++; return ok; }
qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) { // only copy up to the number of samples we have available int numReadSamples = std::min((unsigned) (maxSize / sizeof(int16_t)), samplesAvailable()); // If we're in random access mode, then we consider our number of available read samples slightly // differently. Namely, if anything has been written, we say we have as many samples as they ask for // otherwise we say we have nothing available if (_randomAccessMode) { numReadSamples = _endOfLastWrite ? (maxSize / sizeof(int16_t)) : 0; } if (_nextOutput + numReadSamples > _buffer + _sampleCapacity) { // we're going to need to do two reads to get this data, it wraps around the edge // read to the end of the buffer int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput; memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); if (_randomAccessMode) { memset(_nextOutput, 0, numSamplesToEnd * sizeof(int16_t)); // clear it } // read the rest from the beginning of the buffer memcpy(data + (numSamplesToEnd * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); if (_randomAccessMode) { memset(_buffer, 0, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); // clear it } } else { // read the data memcpy(data, _nextOutput, numReadSamples * sizeof(int16_t)); if (_randomAccessMode) { memset(_nextOutput, 0, numReadSamples * sizeof(int16_t)); // clear it } } // push the position of _nextOutput by the number of samples read _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numReadSamples); return numReadSamples * sizeof(int16_t); }
int AudioRingBuffer::addSilentSamples(int silentSamples) { int samplesRoomFor = _sampleCapacity - samplesAvailable(); if (silentSamples > samplesRoomFor) { // there's not enough room for this write. write as many silent samples as we have room for silentSamples = samplesRoomFor; qCDebug(audio) << "Dropping some silent samples to prevent ring buffer overflow"; } // memset zeroes into the buffer, accomodate a wrap around the end // push the _endOfLastWrite to the correct spot if (_endOfLastWrite + silentSamples <= _buffer + _bufferLength) { memset(_endOfLastWrite, 0, silentSamples * sizeof(int16_t)); } else { int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite; memset(_endOfLastWrite, 0, numSamplesToEnd * sizeof(int16_t)); memset(_buffer, 0, (silentSamples - numSamplesToEnd) * sizeof(int16_t)); } _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, silentSamples); return silentSamples; }
qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) { // only copy up to the number of samples we have available int numReadSamples = std::min((unsigned) (maxSize / sizeof(int16_t)), samplesAvailable()); if (_nextOutput + numReadSamples > _buffer + _sampleCapacity) { // we're going to need to do two reads to get this data, it wraps around the edge // read to the end of the buffer int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput; memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); // read the rest from the beginning of the buffer memcpy(data + (numSamplesToEnd * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); } else { // read the data memcpy(data, _nextOutput, numReadSamples * sizeof(int16_t)); } // push the position of _nextOutput by the number of samples read _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numReadSamples); return numReadSamples * sizeof(int16_t); }
void dabStick::newdataAvailable (int n) { samplesAvailable (n); }
bool DsdiffFileReader::readNextBlock() { bool ok = true; // return false if this is the end of the file if (!samplesAvailable()) { errorMsg = "dsfFileReader::readNextBlock:no more data in file"; ok = false; } dsf2flac_int64 samplesLeft = getLength()-getPosition(); if (ok && checkIdent(compressionType,const_cast<dsf2flac_int8*>("DSD "))) { if (samplesLeft/samplesPerChar < sampleBufferLenPerChan) { // fill the blockBuffer with the idle sample for (dsf2flac_uint32 i=0; i<chanNum*sampleBufferLenPerChan; i++) sampleBuffer[i] = getIdleSample(); if (file.read_uint8(sampleBuffer,chanNum*samplesLeft/samplesPerChar)) { errorMsg = "dsfFileReader::readNextBlock:file read error"; ok = false; } } else if (file.read_uint8(sampleBuffer,chanNum*sampleBufferLenPerChan)) { errorMsg = "dsfFileReader::readNextBlock:file read error"; ok = false; } } else if (ok && checkIdent(compressionType,const_cast<dsf2flac_int8*>("DST "))) { dsf2flac_uint64 chunkStart = file.tellg(); dsf2flac_uint64 chunkSz; dsf2flac_int8 ident[5]; ident[4]='\0'; if (chunkStart > dstChunkEnd) ok = false; // read the chunk header if (ok) ok = readChunkHeader(ident,chunkStart,&chunkSz); // we might have a DSTC chunk, which we will ignore if (ok) if (checkIdent(ident,const_cast<dsf2flac_int8*>("DSTC"))) ok = readChunkHeader(ident,chunkStart,&chunkSz); // decode if (ok) ok = readChunk_DSTF(chunkStart); // make sure we are in the right place for next time file.seekg(chunkStart + chunkSz); } else ok = false; if (!ok) { // fill the blockBuffer with the idle sample for (dsf2flac_uint32 i=0; i<chanNum*sampleBufferLenPerChan; i++) sampleBuffer[i] = getIdleSample(); } bufferCounter++; bufferMarker=0; return ok; }
/// \brief Gets sample data from the oscilloscope and converts it. /// \return 0 on success, libusb error code on error. int Control::getSamples(bool process) { long int errorCode; // Save raw data to temporary buffer unsigned long int dataCount = bufferSize * BUUDAI_CHANNELS * bufferMulti; if (bufferMulti >= 2) { dataCount = dataCount + 4096; } unsigned long int dataLength = dataCount * 1; unsigned char data[dataLength]; usbMutex.lock(); unsigned char res = 0; device->controlTransfer(0, (unsigned char)FIFO_CONTROL, &res, 1, (unsigned char)FIFO_CONTROL_CLEAR, 0, 1); errorCode = device->bulkReadMulti(data, dataLength, 3); //errorCode = device->bulkRead(data, dataLength, 1); // device->controlTransfer(0, (unsigned char)FIFO_CONTROL, &res, 1, (unsigned char)FIFO_CONTROL_CLEAR, 0, 1); usbMutex.unlock(); //usleep(1000000); if (errorCode < 0) return errorCode; // Process the data only if we want it if (process) { // How much data did we really receive? dataLength = errorCode; dataCount = dataLength; samplesMutex.lock(); unsigned long int channelDataCount = dataCount / BUUDAI_CHANNELS; for (int channel = 0; channel < BUUDAI_CHANNELS; channel++) { // Reallocate memory for samples if the sample count has changed if (!samples[channel] || samplesSize[channel] != channelDataCount) { if (samples[channel]) delete samples[channel]; samples[channel] = new double[channelDataCount]; samplesSize[channel] = channelDataCount; } // Convert data from the oscilloscope and write it into the sample buffer unsigned long int bufferPosition = 0 ;//+ triggerPoint * 2; unsigned int bufferFraction = (dataCount / BUUDAI_CHANNELS) / 2; // only use a fraction of samplebuffer, scales with timebase via bufferMulti to catch slow signals on longer timebase. // For buffersizes < 2048 no initial shift is needed, as data fits in fifo without glitch if (bufferMulti >= 2) { bufferPosition = 2048; } if (oldTriggerOffset >= 256 && oldTriggerOffset <= channelDataCount) { bufferPosition = oldTriggerOffset - 256; } // Trigger Hack for rising signal double dataValueOld = 0; int hitCounter = 0; for (unsigned int triggerPositionIndex = 0; triggerPositionIndex < bufferFraction; triggerPositionIndex ++, bufferPosition += 2){ double dataValue = ((double) data[bufferPosition + channel]/sampleRange[channel] - offsetReal[channel])*gainSteps[gain[channel]]*cal[channel]; if (dataValue >= dataValueOld && dataValue >= triggerPositionOffset) { hitCounter++; if (hitCounter >= 4) { bufferPositionOffset = bufferPosition; oldTriggerOffset = bufferPosition; hitCounter = 0; break; } } dataValueOld = dataValue; } // triggerPosition bufferPosition = int(bufferPositionOffset + (triggerPosition * 2)); // shorten data due to trigger offset //channelDataCount = channelDataCount - bufferPosition; // put data on screen for (unsigned long int realPosition = 0; realPosition < channelDataCount ; realPosition++, bufferPosition += 2) { if (bufferPosition >= dataCount) bufferPosition %= dataCount; samples[channel][realPosition] = ((double) data[bufferPosition + channel]/sampleRange[channel] - offsetReal[channel])*gainSteps[gain[channel]]*cal[channel]; } } samplesMutex.unlock(); // limit framerate and load but be somewhat in sync with samplerate to avoid glitches if (bufferMulti < 2) { usleep(32768); } else { // usleep(bufferSize); } emit samplesAvailable(&(samples), &(samplesSize), (double) samplerateMax / samplerateDivider, &(samplesMutex)); } // if (process) return 0; }