Esempio n. 1
0
uint32_t
AudioSink::DrainConverter(uint32_t aMaxFrames)
{
  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());

  if (!mConverter || !mLastProcessedPacket || !aMaxFrames) {
    // nothing to drain.
    return 0;
  }

  RefPtr<AudioData> lastPacket = mLastProcessedPacket.ref();
  mLastProcessedPacket.reset();

  // To drain we simply provide an empty packet to the audio converter.
  AlignedAudioBuffer convertedData =
    mConverter->Process(AudioSampleBuffer(AlignedAudioBuffer())).Forget();

  uint32_t frames = convertedData.Length() / mOutputChannels;
  if (!convertedData.SetLength(std::min(frames, aMaxFrames) * mOutputChannels)) {
    // This can never happen as we were reducing the length of convertData.
    mErrored = true;
    return 0;
  }

  RefPtr<AudioData> data =
    CreateAudioFromBuffer(Move(convertedData), lastPacket);
  if (!data) {
    return 0;
  }
  mProcessedQueue.Push(data);
  return data->mFrames;
}
Esempio n. 2
0
void
AudioSink::NotifyAudioNeeded()
{
  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn(),
             "Not called from the owner's thread");

  // Always ensure we have two processed frames pending to allow for processing
  // latency.
  while (mAudioQueue.GetSize() && (mAudioQueue.IsFinished() ||
                                    mProcessedQueueLength < LOW_AUDIO_USECS ||
                                    mProcessedQueue.GetSize() < 2)) {
    RefPtr<AudioData> data = mAudioQueue.PopFront();

    // Ignore the element with 0 frames and try next.
    if (!data->mFrames) {
      continue;
    }

    if (!mConverter ||
        (data->mRate != mConverter->InputConfig().Rate() ||
         data->mChannels != mConverter->InputConfig().Channels())) {
      SINK_LOG_V("Audio format changed from %u@%uHz to %u@%uHz",
                 mConverter? mConverter->InputConfig().Channels() : 0,
                 mConverter ? mConverter->InputConfig().Rate() : 0,
                 data->mChannels, data->mRate);

      DrainConverter();

      // mFramesParsed indicates the current playtime in frames at the current
      // input sampling rate. Recalculate it per the new sampling rate.
      if (mFramesParsed) {
        // We minimize overflow.
        uint32_t oldRate = mConverter->InputConfig().Rate();
        uint32_t newRate = data->mRate;
        CheckedInt64 result = SaferMultDiv(mFramesParsed, newRate, oldRate);
        if (!result.isValid()) {
          NS_WARNING("Int overflow in AudioSink");
          mErrored = true;
          return;
        }
        mFramesParsed = result.value();
      }

      mConverter =
        MakeUnique<AudioConverter>(
          AudioConfig(data->mChannels, data->mRate),
          AudioConfig(mOutputChannels, mOutputRate));
    }

    // See if there's a gap in the audio. If there is, push silence into the
    // audio hardware, so we can play across the gap.
    // Calculate the timestamp of the next chunk of audio in numbers of
    // samples.
    CheckedInt64 sampleTime =
      TimeUnitToFrames(data->mTime - mStartTime, data->mRate);
    // Calculate the number of frames that have been pushed onto the audio hardware.
    CheckedInt64 missingFrames = sampleTime - mFramesParsed;

    if (!missingFrames.isValid()) {
      NS_WARNING("Int overflow in AudioSink");
      mErrored = true;
      return;
    }

    if (missingFrames.value() > AUDIO_FUZZ_FRAMES) {
      // The next audio packet begins some time after the end of the last packet
      // we pushed to the audio hardware. We must push silence into the audio
      // hardware so that the next audio packet begins playback at the correct
      // time.
      missingFrames = std::min<int64_t>(INT32_MAX, missingFrames.value());
      mFramesParsed += missingFrames.value();

      RefPtr<AudioData> silenceData;
      AlignedAudioBuffer silenceBuffer(missingFrames.value() * data->mChannels);
       if (!silenceBuffer) {
         NS_WARNING("OOM in AudioSink");
         mErrored = true;
         return;
       }
      if (mConverter->InputConfig() != mConverter->OutputConfig()) {
        AlignedAudioBuffer convertedData =
          mConverter->Process(AudioSampleBuffer(Move(silenceBuffer))).Forget();
        silenceData = CreateAudioFromBuffer(Move(convertedData), data);
      } else {
        silenceData = CreateAudioFromBuffer(Move(silenceBuffer), data);
      }
      PushProcessedAudio(silenceData);
    }

    mLastEndTime = data->GetEndTime();
    mFramesParsed += data->mFrames;

    if (mConverter->InputConfig() != mConverter->OutputConfig()) {
      // We must ensure that the size in the buffer contains exactly the number
      // of frames, in case one of the audio producer over allocated the buffer.
      AlignedAudioBuffer buffer(Move(data->mAudioData));
      buffer.SetLength(size_t(data->mFrames) * data->mChannels);

      AlignedAudioBuffer convertedData =
        mConverter->Process(AudioSampleBuffer(Move(buffer))).Forget();
      data = CreateAudioFromBuffer(Move(convertedData), data);
    }
    if (PushProcessedAudio(data)) {
      mLastProcessedPacket = Some(data);
    }
  }

  if (mAudioQueue.IsFinished()) {
    // We have reached the end of the data, drain the resampler.
    DrainConverter();
    mProcessedQueue.Finish();
  }
}
WavetableOscillator::WavetableOscillator() :    baseHz(110.0),
    wavetableSampleRate(44100),
    level("level", 0, 1, 1),
    position("position", 0, 127, 0),
    phase("phase", 0, 1, 0),
    wavetable(128, std::vector<float>(401))
{
    /*
    for (int i = 0; i < wavetable[0].size(); i++) {
        wavetable[0][i] = sinf(2 * float_Pi * ((float)i / wavetable[0].size()));
    }*/

    const int WAVEFORM_SAMPLESIZE = 401;
    //const int MAX_TOKENS_PER_LINE = 20;
    //const char* const DELIMITER = " ";

    File fsA(File::getCurrentWorkingDirectory().getFullPathName() + "/A.txt");
    File fsB(File::getCurrentWorkingDirectory().getFullPathName() + "/B.txt");
    AudioSampleBuffer bufferA, bufferB;
    bufferA = AudioSampleBuffer();
    bufferB = AudioSampleBuffer();

    // traverse the entire first file
    StringArray destLines;
    fsA.readLines(destLines);
    int i = 0;
    for (; i < destLines.strings.size(); i++) {
        wavetable[0][i] = destLines.strings[i].getFloatValue();
    }


    // make sure that up to 401 is filed, continue where <i> left off from while loop
    for (; i < WAVEFORM_SAMPLESIZE; i++) {
        wavetable[0][i] = 0.0;
    }

    // for traversing each float of the waveform
    int j = 0;
    int wavetable_depth = wavetable.size()-1;

    // traverse the entire second file
    StringArray destLines2;
    fsB.readLines(destLines2);

    for (; j < destLines2.strings.size(); j++) {
        wavetable[wavetable_depth][j] = destLines2.strings[j].getFloatValue();
    }

    // make sure that up to 401 is filed, continue where <i> left off from while loop
    for (; j < WAVEFORM_SAMPLESIZE; j++) {
        wavetable[wavetable_depth][j] = 0.0;
    }

    // fill in rest of wavetable
    for (int i = 1; i < wavetable.size()-1; i++) {
        double weight = (double) i / (double) wavetable[i].size();
        for (int j = 0; j < wavetable[i].size(); j++) {
            wavetable[i][j] = (1.0 - weight) * wavetable[0][j] + weight * wavetable[wavetable_depth][j];
        }
    }

    std::cout << "We made it";
}
Esempio n. 4
0
void ResamplingNode::process(AudioSampleBuffer& buffer,
                             MidiBuffer& midiMessages,
                             int& nSamples)
{

    //std::cout << "Resampling node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl;

    // save data at the beginning of each round of processing
    //writeContinuousBuffer(buffer.getSampleData(0), nSamples, 0);


    int nSamps = float(nSamples);
    int valuesNeeded = int(nSamps / ratio);

    if (ratio > 1.0001)
    {
        // pre-apply filter before downsampling
        filter->process(nSamples, buffer.getArrayOfChannels());
    }

    // initialize variables
    tempBuffer->clear();
    int sourceBufferPos = 0;
    int sourceBufferSize = buffer.getNumSamples();
    float subSampleOffset = 0.0;
    int nextPos = (sourceBufferPos + 1) % sourceBufferSize;

    int tempBufferPos;

    // code modified from "juce_ResamplingAudioSource.cpp":

    for (tempBufferPos = 0; tempBufferPos < valuesNeeded; tempBufferPos++)
    {
        float gain = 1.0;
        float alpha = (float) subSampleOffset;
        float invAlpha = 1.0f - alpha;

        for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
        {

            tempBuffer->addFrom(channel, 		// destChannel
                                tempBufferPos,  // destSampleOffset
                                buffer,			// source
                                channel,		// sourceChannel
                                sourceBufferPos,// sourceSampleOffset
                                1,				// number of samples
                                invAlpha*gain);      // gain to apply to source

            tempBuffer->addFrom(channel, 		// destChannel
                                tempBufferPos,   // destSampleOffset
                                buffer,			// source
                                channel,			// sourceChannel
                                nextPos,		 	// sourceSampleOffset
                                1,				// number of samples
                                alpha*gain);     	 // gain to apply to source

        }

        subSampleOffset += ratio;

        while (subSampleOffset >= 1.0)
        {
            if (++sourceBufferPos >= sourceBufferSize)
                sourceBufferPos = 0;

            nextPos = (sourceBufferPos + 1) % sourceBufferSize;
            subSampleOffset -= 1.0;
        }
    }

    // std::cout << sourceBufferPos << " " << tempBufferPos << std::endl;


    if (ratio < 0.9999)
    {

        filter->process(tempBufferPos, tempBuffer->getArrayOfChannels());
        // apply the filter after upsampling
        ///////filter->process (totalSamples, buffer.getArrayOfChannels());
    }
    else if (ratio <= 1.0001)
    {

        // no resampling is being applied, no need to filter, BUT...
        // keep the filter stoked with samples to avoid discontinuities

    }

    // copy the tempBuffer back into the original buffer
    buffer = AudioSampleBuffer(tempBuffer->getArrayOfChannels(), 2, tempBufferPos);//buffer.getNumSamples());

    nSamples = valuesNeeded;

}
Esempio n. 5
0
void AudioResamplingNode::process(AudioSampleBuffer& buffer,
                                  MidiBuffer& midiMessages,
                                  int& nSamples)
{

    int nSamps = nSamples;
    int valuesNeeded;

    if (destBufferIsTempBuffer)
    {
        ratio = float(nSamps) / float(buffer.getNumSamples());
        valuesNeeded = buffer.getNumSamples();
    }
    else
    {
        ratio = sourceBufferSampleRate / destBufferSampleRate;
        valuesNeeded = (int) buffer.getNumSamples() / ratio;
        //std::cout << std::endl;
        //std::cout << "Ratio: " << ratio << std::endl;
        //std::cout << "Values needed: " << valuesNeeded << std::endl;
    }



    if (lastRatio != ratio)
    {
        updateFilter();
        lastRatio = ratio;
    }


    if (ratio > 1.0001)
    {
        // pre-apply filter before downsampling
        filter->process(nSamps, buffer.getArrayOfChannels());
    }


    // initialize variables
    tempBuffer->clear();
    int sourceBufferPos = 0;
    int sourceBufferSize = buffer.getNumSamples();
    float subSampleOffset = 0.0;
    int nextPos = (sourceBufferPos + 1) % sourceBufferSize;

    int tempBufferPos;
    //int totalSamples = 0;

    // code modified from "juce_ResamplingAudioSource.cpp":

    for (tempBufferPos = 0; tempBufferPos < valuesNeeded; tempBufferPos++)
    {
        float gain = 1.0;
        float alpha = (float) subSampleOffset;
        float invAlpha = 1.0f - alpha;

        for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
        {

            tempBuffer->addFrom(channel, 		// destChannel
                                tempBufferPos,  // destSampleOffset
                                buffer,			// source
                                channel,		// sourceChannel
                                sourceBufferPos,// sourceSampleOffset
                                1,				// number of samples
                                invAlpha*gain);      // gain to apply to source

            tempBuffer->addFrom(channel, 		// destChannel
                                tempBufferPos,   // destSampleOffset
                                buffer,			// source
                                channel,			// sourceChannel
                                nextPos,		 	// sourceSampleOffset
                                1,				// number of samples
                                alpha*gain);     	 // gain to apply to source

        }

        subSampleOffset += ratio;



        while (subSampleOffset >= 1.0)
        {
            if (++sourceBufferPos >= sourceBufferSize)
                sourceBufferPos = 0;

            nextPos = (sourceBufferPos + 1) % sourceBufferSize;
            subSampleOffset -= 1.0;
        }
    }

    // std::cout << sourceBufferPos << " " << tempBufferPos << std::endl;


    if (ratio < 0.9999)
    {

        filter->process(tempBufferPos, tempBuffer->getArrayOfChannels());
        // apply the filter after upsampling
        ///////filter->process (totalSamples, buffer.getArrayOfChannels());
    }
    else if (ratio <= 1.0001)
    {

        // no resampling is being applied, no need to filter, BUT...
        // keep the filter stoked with samples to avoid discontinuities

    }

    if (destBufferIsTempBuffer)
    {

        // copy the temp buffer into the original buffer
        buffer = AudioSampleBuffer(tempBuffer->getArrayOfChannels(), 2, tempBufferPos);//buffer.getNumSamples());

    }
    else
    {

        //std::cout << "Copying into dest buffer..." << std::endl;

        // copy the temp buffer into the destination buffer

        int pos = 0;

        while (*tempBuffer->getSampleData(0,pos) != 0)
            pos++;

        int spaceAvailable = destBufferWidth - destBufferPos;
        int blockSize1 = (spaceAvailable > pos) ? pos : spaceAvailable;
        int blockSize2 = (spaceAvailable > pos) ? 0 : (pos - spaceAvailable);

        for (int channel = 0; channel < destBuffer->getNumChannels(); channel++)
        {

            // copy first block
            destBuffer->copyFrom(channel, 		//destChannel
                                 destBufferPos, //destStartSample
                                 *tempBuffer, 	//source
                                 channel, 		//sourceChannel
                                 0, 			//sourceStartSample
                                 blockSize1  //numSamples
                                );

            // copy second block
            destBuffer->copyFrom(channel, 		//destChannel
                                 0, 			//destStartSample
                                 *tempBuffer, 	//source
                                 channel, 		//sourceChannel
                                 blockSize1, 	//sourceStartSample
                                 blockSize2  //numSamples
                                );

        }

        //destBufferPos = (spaceAvailable > tempBufferPos) ? destBufferPos

        destBufferPos += pos;
        destBufferPos %= destBufferWidth;

        //std::cout << "Temp buffer position: " << tempBufferPos << std::endl;
        //std::cout << "Resampling node value:" << *destBuffer->getSampleData(0,0) << std::endl;

    }

}