Esempio n. 1
0
void LooperLayer::setSamples(const SamplesBuffer &samples)
{
    zero();

    uint samplesToCopy = qMin(samples.getFrameLenght(), lastCycleLenght);
    if (!samplesToCopy) {
        return;
    }

    uint bytesToCopy =  samplesToCopy * sizeof(float);

    Q_ASSERT(leftChannel.capacity() >= samplesToCopy);
    Q_ASSERT(rightChannel.capacity() >= samplesToCopy);

    std::memcpy(&(leftChannel[0]), samples.getSamplesArray(0), bytesToCopy);
    if (samples.isMono())
        std::memcpy(&(rightChannel[0]), samples.getSamplesArray(0), bytesToCopy);
    else
        std::memcpy(&(rightChannel[0]), samples.getSamplesArray(1), bytesToCopy);

    availableSamples = samplesToCopy;


    // rebuild peaks cache
    lastCacheComputationSample = 0;
    peaksCache.clear();

    if (lastSamplesPerPeak) {
        while (availableSamples - lastCacheComputationSample >= lastSamplesPerPeak) { // enough samples to cache a new max peak?
            peaksCache.push_back(computeMaxPeak(lastCacheComputationSample, lastSamplesPerPeak));
            lastCacheComputationSample += lastSamplesPerPeak;
        }
    }

}
Esempio n. 2
0
void LooperLayer::append(const SamplesBuffer &samples, uint samplesToAppend, uint startPosition)
{
    int toAppend = qMin(static_cast<uint>(leftChannel.capacity() - startPosition), samplesToAppend);

    if (!toAppend) {
        qCritical() << "toAppend:" << toAppend;
        return;
    }

    const uint sizeInBytes = toAppend * sizeof(float);

    const int secondChannelIndex = samples.isMono() ? 0 : 1;
    std::memcpy(&(leftChannel[0]) + startPosition, samples.getSamplesArray(0), sizeInBytes);
    std::memcpy(&(rightChannel[0]) + startPosition, samples.getSamplesArray(secondChannelIndex), sizeInBytes);

    availableSamples += toAppend;

    //Q_ASSERT(availableSamples <= leftChannel.capacity());

    // build peaks cache
    if (lastSamplesPerPeak) {
        if (lastCacheComputationSample < startPosition - lastSamplesPerPeak)
            lastCacheComputationSample = startPosition;

        while ((startPosition + samplesToAppend) - lastCacheComputationSample >= lastSamplesPerPeak && lastCacheComputationSample  < leftChannel.size()) { // enough samples to cache a new max peak?
            peaksCache.push_back(computeMaxPeak(lastCacheComputationSample, lastSamplesPerPeak));
            lastCacheComputationSample += lastSamplesPerPeak;
        }
    }
}
Esempio n. 3
0
void SamplesBuffer::set(const SamplesBuffer& buffer, unsigned int bufferOffset, unsigned int samplesToCopy, unsigned int internalOffset){

    if(buffer.channels <= 0 || channels <= 0){
        return;
    }

    unsigned int framesToProcess = std::min(samplesToCopy, buffer.getFrameLenght() - bufferOffset);
    if(framesToProcess > buffer.frameLenght){//não processa mais samples do que a quantidade existente em buffer
        framesToProcess = buffer.frameLenght;
    }
    if((int)(internalOffset + framesToProcess)  > this->getFrameLenght()){
        framesToProcess = (internalOffset + framesToProcess) - this->getFrameLenght();
    }

    if(channels == buffer.channels){//channels number are equal
        for (unsigned int c = 0; c < channels; ++c) {
            for (unsigned int s = 0; s < framesToProcess; ++s) {
                samples[c][s + internalOffset] = buffer.samples[c][s + bufferOffset];
            }
        }
    }
    else{//different number of channels
        if(!isMono()){//copy every &buffer samples to LR in this buffer
            if(!buffer.isMono()){
                int channelsToCopy = qMin(channels, buffer.channels);
                for (int c = 0; c < channelsToCopy; ++c) {
                    for (unsigned int s = 0; s < framesToProcess; ++s) {
                        samples[c][s + internalOffset] = buffer.samples[c][s + bufferOffset];
                    }
                }
            }
            else{
                for (unsigned int s = 0; s < framesToProcess; ++s) {
                    samples[0][s + internalOffset] = buffer.samples[0][s + bufferOffset];
                    samples[1][s + internalOffset] = buffer.samples[0][s + bufferOffset];
                }
            }
        }
        else{//this buffer is mono, but the buffer in parameter is not! Mix down the stereo samples in one mono sample value.
            for (unsigned int s = 0; s < framesToProcess; ++s) {
                samples[0][s + internalOffset] = (buffer.samples[0][s + bufferOffset] + buffer.samples[1][s + bufferOffset]) / 2;
            }
        }
    }

}
Esempio n. 4
0
void SamplesBuffer::set(const SamplesBuffer &buffer, uint bufferOffset, uint samplesToCopy, uint internalOffset)
{
    if (buffer.channels == 0 || channels == 0)
        return;

    unsigned int framesToProcess = std::min(samplesToCopy, buffer.getFrameLenght() - bufferOffset);
    if (framesToProcess + bufferOffset > buffer.frameLenght) // fixing bug in some built-in metronome sounds
        return ;

    if ((uint)(internalOffset + framesToProcess) > this->getFrameLenght())
        framesToProcess = (internalOffset + framesToProcess) - this->getFrameLenght();

    const uint bytesToProcess = framesToProcess * sizeof(float);
    if (!bytesToProcess)
        return;

    if (channels == buffer.channels) {// channels number are equal
        for (unsigned int c = 0; c < channels; ++c) {
            std::memcpy(&(samples[c][internalOffset]), &(buffer.samples[c][bufferOffset]), bytesToProcess);
        }
    }
    else { // different number of channels
        if (!isMono()) { // copy every &buffer samples to LR in this buffer
            if (!buffer.isMono()) {
                int channelsToCopy = qMin(channels, buffer.channels);
                for (int c = 0; c < channelsToCopy; ++c) {
                    Q_ASSERT(internalOffset < samples[c].size());
                    Q_ASSERT(bufferOffset < buffer.samples[c].size());
                    Q_ASSERT(bufferOffset + framesToProcess < buffer.samples[c].size());
                    Q_ASSERT(internalOffset + framesToProcess < samples[c].size());
                    std::memcpy(&(samples[c][internalOffset]), &(buffer.samples[c][bufferOffset]), bytesToProcess);
                }
            } else {
                std::memcpy(&(samples[0][internalOffset]), &(buffer.samples[0][bufferOffset]), bytesToProcess);
                std::memcpy(&(samples[1][internalOffset]), &(buffer.samples[0][bufferOffset]), bytesToProcess);
            }
        } else { // this buffer is mono, but the buffer in parameter is not! Mix down the stereo samples in one mono sample value.
            for (unsigned int s = 0; s < framesToProcess; ++s) {
                const int index = s + bufferOffset;
                float v = (buffer.samples[0][index] + buffer.samples[1][index])/2.0f;
                samples[0][s + internalOffset] = v;
            }
        }
    }
}
Esempio n. 5
0
void LooperLayer::mixTo(SamplesBuffer &outBuffer, uint samplesToMix, uint intervalPosition, float looperMainGain)
{
    bool canMix = samplesToMix > 0 && (muteState == LooperLayer::Unmuted || muteState == LooperLayer::WaitingToMute);
    if (canMix) {
        float *internalChannels[] = {&(leftChannel[0]), &(rightChannel[0])};
        const uint secondChannelIndex = (outBuffer.isMono()) ? 0 : 1;
        float *bufferChannels[] = {outBuffer.getSamplesArray(0), outBuffer.getSamplesArray(secondChannelIndex)};
        uint channels = outBuffer.getChannels();

        const float mainGain = looperMainGain * gain;
        const float finalLeftGain = mainGain * leftGain;
        const float finalRightGain = mainGain * rightGain;
        float gains[] = {finalLeftGain, finalRightGain};
        for (uint c = 0; c < channels; ++c) {
            for (uint s = 0; s < samplesToMix; ++s) {
                const uint offset = s + intervalPosition;
                bufferChannels[c][s] += internalChannels[c][offset] * gains[c];
            }
        }
    }
}
Esempio n. 6
0
void LooperLayer::overdub(const SamplesBuffer &samples, uint samplesToMix, uint startPosition)
{
    if (!samples.isMono()) {
        float *internalChannels[] = {&(leftChannel[startPosition]), &(rightChannel[startPosition])};
        float *samplesArray[] = {samples.getSamplesArray(0), samples.getSamplesArray(1)};
        for (uint s = 0; s < samplesToMix; ++s) {
            internalChannels[0][s] += samplesArray[0][s]; // left channel
            internalChannels[1][s] += samplesArray[1][s]; // right channel
        }
    }
    else {
        float *internalChannels[] = {&(leftChannel[startPosition]), &(rightChannel[startPosition])};
        float *samplesArray = samples.getSamplesArray(0);
        for (uint s = 0; s < samplesToMix; ++s) {
            internalChannels[0][s] += samplesArray[s];
        }
    }

    if (availableSamples < startPosition + samplesToMix)
        availableSamples = startPosition + samplesToMix;

    // build peaks cache when overdubbing
    if (lastSamplesPerPeak) {
        const uint position = startPosition + samplesToMix;
        while (position - lastCacheComputationSample >= lastSamplesPerPeak) { // enough samples to cache a new max peak?
            const int peakIndex = (position/lastSamplesPerPeak) - 1;
            float lastPeak = computeMaxPeak(lastCacheComputationSample, lastSamplesPerPeak);
            if (peakIndex >= 0 && static_cast<uint>(peakIndex) < peaksCache.size())
                peaksCache[peakIndex] = lastPeak;
            else
                peaksCache.push_back(lastPeak);

            lastCacheComputationSample += lastSamplesPerPeak;
        }
    }
}