//==============================================================================
void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
{
    if (processor != processorToPlay)
    {
        if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0)
        {
            processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans,
                                                   sampleRate, blockSize);

            processorToPlay->prepareToPlay (sampleRate, blockSize);
        }

        AudioProcessor* oldOne;

        {
            const ScopedLock sl (lock);
            oldOne = isPrepared ? processor : nullptr;
            processor = processorToPlay;
            isPrepared = true;
        }

        if (oldOne != nullptr)
            oldOne->releaseResources();
    }
}
//==============================================================================
void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
{
    if (processor != processorToPlay)
    {
        if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0)
        {
            processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, sampleRate, blockSize);

            const bool supportsDouble = processorToPlay->supportsDoublePrecisionProcessing() && isDoublePrecision;
            AudioProcessor::ProcessingPrecision precision = supportsDouble ? AudioProcessor::doublePrecision
                                                                           : AudioProcessor::singlePrecision;

            processorToPlay->setProcessingPrecision (precision);
            processorToPlay->prepareToPlay (sampleRate, blockSize);
        }

        AudioProcessor* oldOne;

        {
            const ScopedLock sl (lock);
            oldOne = isPrepared ? processor : nullptr;
            processor = processorToPlay;
            isPrepared = true;
        }

        if (oldOne != nullptr)
            oldOne->releaseResources();
    }
}
void PMixInterpolationSpaceLayout::mouseDoubleClick (const MouseEvent& e)
{
  if(graphEditor.getLassoSelection().getNumSelected() == 1)
  {
    NodeComponent* selectedItem = dynamic_cast<NodeComponent*>(graphEditor.getLassoSelection().getSelectedItem(0));
    
    if (selectedItem)
    {
      AudioProcessor* proc = audioEngine.getDoc().getNodeForId(selectedItem->nodeID)->getProcessor();
      
      bool hasParams = (proc->getNumParameters() > 0);

      if (hasParams)
      {
        if (!InternalPluginFormat::isInternalFormat(proc->getName()))
        {
          double x = (double) e.getMouseDownX()/getWidth();
          double y = (double) e.getMouseDownY()/getHeight();
          
          audioEngine.getDoc().addPreset(selectedItem->nodeID, x, y);
        }
      }
    }
  }
}
FilterIOConfigurationWindow::FilterIOConfigurationWindow (AudioProcessor& p)
   : AudioProcessorEditor (&p),
     title ("title", p.getName())
{
    setOpaque (true);

    title.setFont (title.getFont().withStyle (Font::bold));
    addAndMakeVisible (title);

    {
        ScopedLock renderLock (p.getCallbackLock());
        p.suspendProcessing (true);
        p.releaseResources();
    }

    if (p.getBusCount (true)  > 0 || p.canAddBus (true))
    {
        inConfig.reset (new InputOutputConfig (*this, true));
        addAndMakeVisible (inConfig.get());
    }

    if (p.getBusCount (false) > 0 || p.canAddBus (false))
    {
        outConfig.reset (new InputOutputConfig (*this, false));
        addAndMakeVisible (outConfig.get());
    }

    currentLayout = p.getBusesLayout();
    setSize (400, (inConfig != nullptr && outConfig != nullptr ? 160 : 0) + 200);
}
Example #5
0
//------------------------------------------------------------------------------
void Mapping::updateParameter(float val)
{
	AudioProcessor *filter = filterGraph->getNodeForId(plugin)->getProcessor();

	if(parameter == -1)
	{
		BypassableInstance *bypassable = dynamic_cast<BypassableInstance *>(filter);

		if(bypassable)
			bypassable->setBypass(val > 0.5f);
	}
	else
		filter->setParameter(parameter, val);
}
bool SndFileAudioFileReader::run(AudioProcessor& processor)
{
    if (input_file_ == nullptr) {
        return false;
    }

    const int BUFFER_SIZE = 16384;

    short input_buffer[BUFFER_SIZE];

    sf_count_t frames_to_read = BUFFER_SIZE / info_.channels;
    sf_count_t frames_read    = frames_to_read;

    sf_count_t total_frames_read = 0;

    bool success = true;

    success = processor.init(info_.samplerate, info_.channels, BUFFER_SIZE);

    if (success) {
        showProgress(0, info_.frames);

        while (success && frames_read == frames_to_read) {
            frames_read = sf_readf_short(
                input_file_,
                input_buffer,
                frames_to_read
            );

            success = processor.process(
                input_buffer,
                static_cast<int>(frames_read)
            );

            total_frames_read += frames_read;

            showProgress(total_frames_read, info_.frames);
        }

        output_stream << "\nRead " << total_frames_read << " frames\n";

        processor.done();
    }

    close();

    return success;
}
static int callback(const void *inputBuffer,
                    void *outputBuffer,
                    unsigned long framesPerBuffer,
                    const PaStreamCallbackTimeInfo* timeInfo,
                    PaStreamCallbackFlags statusFlags,
                    void *userData )
{
    AudioProcessor* audioDevice = (AudioProcessor*)userData;
    float** output = (float**)outputBuffer;
    float** input = (float**)inputBuffer;

//    if(audioDevice->isPrepared())
        audioDevice->render(input, audioDevice->getNumInputChannels(), output, audioDevice->getNumOutputChannels(), framesPerBuffer);
    
    return 0;
}
    void update (AudioProcessor& audioProcessor, bool forceLegacyParamIDs)
    {
        clear();

        legacyParamIDs = forceLegacyParamIDs;

        auto numParameters = audioProcessor.getNumParameters();
        usingManagedParameters = (audioProcessor.getParameters().size() == numParameters) && (! legacyParamIDs);

        for (int i = 0; i < numParameters; ++i)
        {
            AudioProcessorParameter* param = usingManagedParameters ? audioProcessor.getParameters()[i]
                                                                    : (legacy.add (new LegacyAudioParameter (audioProcessor, i)));
            params.add (param);
        }
    }
 ProcessorParameterPropertyComp (const String& name, AudioProcessor& owner_, const int index_)
     : PropertyComponent (name),
       owner (owner_),
       index (index_),
       paramHasChanged (false),
       slider (owner_, index_)
 {
     startTimer (100);
     addAndMakeVisible (&slider);
     owner_.addListener (this);
 }
    static int getParamIndex (AudioProcessor& processor, AudioProcessorParameter* param) noexcept
    {
        if (auto* legacy = dynamic_cast<LegacyAudioParameter*> (param))
        {
            return legacy->parameterIndex;
        }
        else
        {
            auto n = processor.getNumParameters();
            jassert (n == processor.getParameters().size());

            for (int i = 0; i < n; ++i)
            {
                if (processor.getParameters()[i] == param)
                    return i;
            }
        }

        return -1;
    }
void PMixInterpolationSpaceLayout::mouseDown (const MouseEvent& e)
{
  selectedItems.deselectAll();
  
  if (e.mods.isPopupMenu())
  {
    if(graphEditor.getLassoSelection().getNumSelected() == 1)
    {
      NodeComponent* selectedItem = dynamic_cast<NodeComponent*>(graphEditor.getLassoSelection().getSelectedItem(0));
      
      if (selectedItem)
      {
        AudioProcessor* proc = audioEngine.getDoc().getNodeForId(selectedItem->nodeID)->getProcessor();
        
        PopupMenu m;
        
        bool hasParams = (proc->getNumParameters() > 0);

        m.addItem (1, TRANS("Add preset for node"), hasParams);
        
        const int r = m.show();
        
        if (r == 1)
        {
          if (!InternalPluginFormat::isInternalFormat(proc->getName()))
          {
            double x = (double) e.getMouseDownX()/getWidth();
            double y = (double) e.getMouseDownY()/getHeight();

            audioEngine.getDoc().addPreset(selectedItem->nodeID, x, y);
          }
        }
      }
    }
  }
  else
  {
    addChildComponent (lassoComp);
    lassoComp.beginLasso (e, this);
  }
}
Example #12
0
PluginWindow* PluginWindow::getWindowFor (AudioProcessorGraph::Node* const node,
                                          WindowFormatType type)
{
  jassert (node != nullptr);
  
  for (int i = activePluginWindows.size(); --i >= 0;)
    if (activePluginWindows.getUnchecked(i)->owner == node
        && activePluginWindows.getUnchecked(i)->type == type)
      return activePluginWindows.getUnchecked(i);
  
  AudioProcessor* processor = node->getProcessor();
  AudioProcessorEditor* ui = nullptr;
  
  if (type == Normal)
  {
    ui = processor->createEditorIfNeeded();
    
    if (ui == nullptr)
      type = Generic;
  }
  
  if (ui == nullptr)
  {
    //if (type == Generic || type == Parameters)
      //ui = new PMixGenericAudioProcessorEditor (processor);
//    else if (type == Programs)
//      ui = new ProgramAudioProcessorEditor (processor);
  }
  
  if (ui != nullptr)
  {
    if (AudioPluginInstance* const plugin = dynamic_cast<AudioPluginInstance*> (processor))
      ui->setName (plugin->getName());
    
    return new PluginWindow (ui, node, type);
  }
  
  return nullptr;
}
        ParamSlider (AudioProcessor& p, int paramIndex)  : owner (p), index (paramIndex)
        {
            const int steps = owner.getParameterNumSteps (index);
            const AudioProcessorParameter::Category category = p.getParameterCategory (index);
            const bool isLevelMeter = (((category & 0xffff0000) >> 16) == 2);

            if (steps > 1 && steps < 0x7fffffff)
                setRange (0.0, 1.0, 1.0 / (steps - 1.0));
            else
                setRange (0.0, 1.0);

            setEnabled (! isLevelMeter);
            setSliderStyle (Slider::LinearBar);
            setTextBoxIsEditable (false);
            setScrollWheelEnabled (true);
        }
bool SndFileAudioFileReader::run(AudioProcessor& processor)
{
    if (input_file_ == nullptr) {
        return false;
    }

    const int BUFFER_SIZE = 16384;

    float float_buffer[BUFFER_SIZE];
    short input_buffer[BUFFER_SIZE];

    const int sub_type = info_.format & SF_FORMAT_SUBMASK;

    const bool is_floating_point = sub_type == SF_FORMAT_FLOAT ||
                                   sub_type == SF_FORMAT_DOUBLE;

    sf_count_t frames_to_read = BUFFER_SIZE / info_.channels;
    sf_count_t frames_read    = frames_to_read;

    sf_count_t total_frames_read = 0;

    bool success = true;

    success = processor.init(info_.samplerate, info_.channels, BUFFER_SIZE);

    if (success) {
        showProgress(0, info_.frames);

        while (success && frames_read == frames_to_read) {
            if (is_floating_point) {
                frames_read = sf_readf_float(
                    input_file_,
                    float_buffer,
                    frames_to_read
                );

                // Scale floating-point samples from [-1.0, 1.0] to 16-bit
                // integer range. Note: we don't use SFC_SET_SCALE_FLOAT_INT_READ
                // as this scales using the overall measured waveform peak
                // amplitude, resulting in an unwanted amplitude change.

                for (int i = 0; i < frames_read * info_.channels; ++i) {
                    input_buffer[i] = static_cast<short>(
                        float_buffer[i] * std::numeric_limits<short>::max()
                    );
                }
            }
            else {
                frames_read = sf_readf_short(
                    input_file_,
                    input_buffer,
                    frames_to_read
                );
            }

            success = processor.process(
                input_buffer,
                static_cast<int>(frames_read)
            );

            total_frames_read += frames_read;

            showProgress(total_frames_read, info_.frames);
        }

        output_stream << "\nRead " << total_frames_read << " frames\n";

        processor.done();
    }

    close();

    return success;
}
bool Mp3AudioFileReader::run(AudioProcessor& processor)
{
    if (file_ == nullptr) {
        return false;
    }

    enum {
        STATUS_OK,
        STATUS_INIT_ERROR,
        STATUS_READ_ERROR,
        STATUS_PROCESS_ERROR
    } status = STATUS_OK;

    unsigned char input_buffer[INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
    unsigned char* guard_ptr = nullptr;
    unsigned long frame_count = 0;

    short output_buffer[OUTPUT_BUFFER_SIZE];
    short* output_ptr = output_buffer;
    const short* const output_buffer_end = output_buffer + OUTPUT_BUFFER_SIZE;

    int channels = 0;

    // Decoding options can here be set in the options field of the stream
    // structure.

    // {1} When decoding from a file we need to know when the end of the file is
    // reached at the same time as the last bytes are read (see also the comment
    // marked {3} below). Neither the standard C fread() function nor the POSIX
    // read() system call provides this feature. We thus need to perform our
    // reads through an interface having this feature, this is implemented here
    // by the bstdfile.c module.

    BStdFile bstd_file(file_);

    // Initialize the structures used by libmad.
    MadStream stream;
    MadFrame frame;
    MadSynth synth;

    mad_timer_t timer;
    mad_timer_reset(&timer);

    // This is the decoding loop.

    for (;;) {
        // The input bucket must be filled if it becomes empty or if it's the
        // first execution of the loop.

        if (stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) {
            size_t read_size;
            size_t remaining;
            unsigned char* read_start;

            // {2} libmad may not consume all bytes of the input buffer. If the
            // last frame in the buffer is not wholly contained by it, then that
            // frame's start is pointed by the next_frame member of the stream
            // structure. This common situation occurs when mad_frame_decode()
            // fails, sets the stream error code to MAD_ERROR_BUFLEN, and sets
            // the next_frame pointer to a non-NULL value. (See also the comment
            // marked {4} below.)
            //
            // When this occurs, the remaining unused bytes must be put back at
            // the beginning of the buffer and taken in account before refilling
            // the buffer. This means that the input buffer must be large enough
            // to hold a whole frame at the highest observable bit-rate
            // (currently 448 kb/s). XXX=XXX Is 2016 bytes the size of the
            // largest frame? (448000*(1152/32000))/8

            if (stream.next_frame != nullptr) {
                remaining = stream.bufend - stream.next_frame;
                memmove(input_buffer, stream.next_frame, remaining);
                read_start = input_buffer + remaining;
                read_size  = INPUT_BUFFER_SIZE - remaining;
            }
            else {
                read_size  = INPUT_BUFFER_SIZE;
                read_start = input_buffer;
                remaining = 0;
            }

            // Fill-in the buffer. If an error occurs print a message and leave
            // the decoding loop. If the end of stream is reached we also leave
            // the loop but the return status is left untouched.

            read_size = bstd_file.read(read_start, 1, read_size);

            if (read_size <= 0) {
                if (ferror(file_)) {
                    error_stream << "\nRead error on bit-stream: "
                                 << strerror(errno) << '\n';
                    status = STATUS_READ_ERROR;
                }

                break;
            }

            // {3} When decoding the last frame of a file, it must be followed
            // by MAD_BUFFER_GUARD zero bytes if one wants to decode that last
            // frame. When the end of file is detected we append that quantity
            // of bytes at the end of the available data. Note that the buffer
            // can't overflow as the guard size was allocated but not used the
            // the buffer management code. (See also the comment marked {1}.)
            //
            // In a message to the mad-dev mailing list on May 29th, 2001, Rob
            // Leslie explains the guard zone as follows:
            //
            //    "The reason for MAD_BUFFER_GUARD has to do with the way
            //    decoding is performed. In Layer III, Huffman decoding may
            //    inadvertently read a few bytes beyond the end of the buffer in
            //    the case of certain invalid input. This is not detected until
            //    after the fact. To prevent this from causing problems, and
            //    also to ensure the next frame's main_data_begin pointer is
            //    always accessible, MAD requires MAD_BUFFER_GUARD (currently 8)
            //    bytes to be present in the buffer past the end of the current
            //    frame in order to decode the frame."

            if (bstd_file.eof()) {
                guard_ptr = read_start + read_size;
                memset(guard_ptr, 0, MAD_BUFFER_GUARD);
                read_size += MAD_BUFFER_GUARD;
            }

            // Pipe the new buffer content to libmad's stream decoder facility.
            mad_stream_buffer(&stream, input_buffer, read_size + remaining);
            stream.error = MAD_ERROR_NONE;
        }

        // Decode the next MPEG frame. The streams is read from the buffer, its
        // constituents are break down and stored the the frame structure, ready
        // for examination/alteration or PCM synthesis. Decoding options are
        // carried in the frame structure from the stream structure.
        //
        // Error handling: mad_frame_decode() returns a non zero value when an
        // error occurs. The error condition can be checked in the error member
        // of the stream structure. A mad error is recoverable or fatal, the
        // error status is checked with the MAD_RECOVERABLE macro.
        //
        // {4} When a fatal error is encountered all decoding activities shall
        // be stopped, except when a MAD_ERROR_BUFLEN is signaled. This
        // condition means that the mad_frame_decode() function needs more input
        // to complete its work. One shall refill the buffer and repeat the
        // mad_frame_decode() call. Some bytes may be left unused at the end of
        // the buffer if those bytes forms an incomplete frame. Before
        // refilling, the remaining bytes must be moved to the beginning of the
        // buffer and used for input for the next mad_frame_decode() invocation.
        // (See the comments marked {2} earlier for more details.)
        //
        // Recoverable errors are caused by malformed bit-streams, in this case
        // one can call again mad_frame_decode() in order to skip the faulty
        // part and re-sync to the next frame.

        if (mad_frame_decode(&frame, &stream)) {
            if (MAD_RECOVERABLE(stream.error)) {
                // Do not print a message if the error is a loss of
                // synchronization and this loss is due to the end of stream
                // guard bytes. (See the comment marked {3} above for more
                // information about guard bytes.)

                if (stream.error != MAD_ERROR_LOSTSYNC ||
                    stream.this_frame != guard_ptr) {

                    // For any MP3 file we typically see two errors in the
                    // first frame processed:
                    // - lost synchronization
                    // - reserved header layer value
                    // This seems to be OK, so don't print these

                    if (frame_count != 0) {
                        error_stream << "\nRecoverable frame level error: "
                                     << mad_stream_errorstr(&stream) << '\n';
                    }
                }

                continue;
            }
            else {
                if (stream.error == MAD_ERROR_BUFLEN) {
                    continue;
                }
                else {
                    error_stream << "\nUnrecoverable frame level error: "
                                 << mad_stream_errorstr(&stream) << '\n';
                    status = STATUS_READ_ERROR;
                    break;
                }
            }
        }

        // Display the characteristics of the stream's first frame. The first
        // frame is representative of the entire stream.

        if (frame_count == 0) {
            const int sample_rate = frame.header.samplerate;
            channels = MAD_NCHANNELS(&frame.header);

            dumpInfo(output_stream, frame.header);

            if (!processor.init(sample_rate, channels, OUTPUT_BUFFER_SIZE)) {
                status = STATUS_PROCESS_ERROR;
                break;
            }

            showProgress(0, file_size_);
        }

        // Accounting. The computed frame duration is in the frame header
        // structure. It is expressed as a fixed point number whole data type is
        // mad_timer_t. It is different from the samples fixed point format and
        // unlike it, it can't directly be added or subtracted. The timer module
        // provides several functions to operate on such numbers. Be careful
        // there, as some functions of libmad's timer module receive some of
        // their mad_timer_t arguments by value!

        frame_count++;
        mad_timer_add(&timer, frame.header.duration);

        // Once decoded the frame is synthesized to PCM samples. No errors are
        // reported by mad_synth_frame();

        mad_synth_frame(&synth, &frame);

        // Synthesized samples must be converted from libmad's fixed point
        // number to the consumer format. Here we use signed 16 bit integers on
        // two channels. Integer samples are temporarily stored in a buffer that
        // is flushed when full.

        for (int i = 0; i < synth.pcm.length; i++) {
            // Left channel
            short sample = MadFixedToSshort(synth.pcm.samples[0][i]);

            *output_ptr++ = sample;

            // Right channel. If the decoded stream is monophonic then the right
            // output channel is the same as the left one.

            if (MAD_NCHANNELS(&frame.header) == 2) {
                sample = MadFixedToSshort(synth.pcm.samples[1][i]);
                *output_ptr++ = sample;
            }

            // Flush the output buffer if it is full

            if (output_ptr == output_buffer_end) {
                long pos = ftell(file_);

                showProgress(pos, file_size_);

                bool success = processor.process(
                    output_buffer,
                    OUTPUT_BUFFER_SIZE / channels
                );

                if (!success) {
                    status = STATUS_PROCESS_ERROR;
                    break;
                }

                output_ptr = output_buffer;
            }
        }
    }

    // If the output buffer is not empty and no error occurred during the last
    // write, then flush it.

    if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) {
        int buffer_size = static_cast<int>(output_ptr - output_buffer);

        bool success = processor.process(output_buffer, buffer_size / channels);

        if (!success) {
            status = STATUS_PROCESS_ERROR;
        }
    }

    // Accounting report if no error occurred.

    if (status == STATUS_OK) {
        // Report 100% done.
        showProgress(file_size_, file_size_);

        char buffer[80];

        // The duration timer is converted to a human readable string with the
        // versatile, but still constrained mad_timer_string() function, in a
        // fashion not unlike strftime(). The main difference is that the timer
        // is broken into several values according some of its arguments. The
        // units and fracunits arguments specify the intended conversion to be
        // executed.
        //
        // The conversion unit (MAD_UNIT_MINUTES in our example) also specify
        // the order and kind of conversion specifications that can be used in
        // the format string.
        //
        // It is best to examine libmad's timer.c source-code for details of the
        // available units, fraction of units, their meanings, the format
        // arguments, etc.

        mad_timer_string(timer, buffer, "%lu:%02lu.%03u",
            MAD_UNITS_MINUTES, MAD_UNITS_MILLISECONDS, 0);

        output_stream << "\nFrames decoded: " << frame_count
                      << " (" << buffer << ")\n";
    }

    processor.done();

    close();

    return status == STATUS_OK;
}
 String getParamID (AudioProcessor& processor, int idx) const noexcept
 {
     return usingManagedParameters ? processor.getParameterID (idx) : String (idx);
 }