BEGIN_JUCE_NAMESPACE #include "juce_AudioSubsectionReader.h" //============================================================================== AudioSubsectionReader::AudioSubsectionReader (AudioFormatReader* const source_, const int64 startSample_, const int64 length_, const bool deleteSourceWhenDeleted_) : AudioFormatReader (0, source_->getFormatName()), source (source_), startSample (startSample_), deleteSourceWhenDeleted (deleteSourceWhenDeleted_) { length = jmin (jmax ((int64) 0, source->lengthInSamples - startSample), length_); sampleRate = source->sampleRate; bitsPerSample = source->bitsPerSample; lengthInSamples = length; numChannels = source->numChannels; usesFloatingPointData = source->usesFloatingPointData; }
//============================================================================== int MemoryBlock::getBitRange (const size_t bitRangeStart, size_t numBits) const noexcept { int res = 0; size_t byte = bitRangeStart >> 3; int offsetInByte = (int) bitRangeStart & 7; size_t bitsSoFar = 0; while (numBits > 0 && (size_t) byte < size) { const int bitsThisTime = jmin ((int) numBits, 8 - offsetInByte); const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte; res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar); bitsSoFar += bitsThisTime; numBits -= bitsThisTime; ++byte; offsetInByte = 0; } return res; }
static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, const uint32 timeOutTime, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext) { size_t totalHeaderSent = 0; while (totalHeaderSent < requestHeader.getSize()) { if (Time::getMillisecondCounter() > timeOutTime) return false; const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent)); if (send (socketHandle, static_cast <const char*> (requestHeader.getData()) + totalHeaderSent, numToSend, 0) != numToSend) return false; totalHeaderSent += numToSend; if (progressCallback != nullptr && ! progressCallback (progressCallbackContext, totalHeaderSent, requestHeader.getSize())) return false; } return true; }
int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWrite) { if (numBytesToWrite < 0) numBytesToWrite = std::numeric_limits<int64>::max(); int numWritten = 0; while (numBytesToWrite > 0 && ! source.isExhausted()) { char buffer [8192]; const int num = source.read (buffer, (int) jmin (numBytesToWrite, (int64) sizeof (buffer))); if (num <= 0) break; write (buffer, num); numBytesToWrite -= num; numWritten += num; } return numWritten; }
void MainHostWindow::filesDropped (const StringArray& files, int x, int y) { GraphDocumentComponent* const graphEditor = getGraphEditor(); if (graphEditor != nullptr) { if (files.size() == 1 && File (files[0]).hasFileExtension (filenameSuffix)) { if (graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk) graphEditor->graph.loadFrom (File (files[0]), true); } else { OwnedArray <PluginDescription> typesFound; knownPluginList.scanAndAddDragAndDroppedFiles (formatManager, files, typesFound); Point<int> pos (graphEditor->getLocalPoint (this, Point<int> (x, y))); for (int i = 0; i < jmin (5, typesFound.size()); ++i) createPlugin (typesFound.getUnchecked(i), pos.getX(), pos.getY()); } } }
void JLickshotProcessorBase::process(juce::AudioSampleBuffer &buffer, juce::MidiBuffer &midiData, int numSamples) { keyState_.processNextMidiBuffer (midiData, 0, numSamples, true); synth_.renderNextBlock (buffer, midiData, 0, numSamples); if (delayIsActive_) { delay_.processBlock(buffer); } if(reverbIsActive_){ mVerb_.process(buffer.getArrayOfReadPointers(), buffer.getArrayOfWritePointers(), numSamples); } const int channels = jmin(buffer.getNumChannels(), delay_.getNumChannels()); for(int i = 0; i < channels; i++){ buffer.applyGainRamp (i, 0, numSamples, lastGain_, gain_); } lastGain_ = gain_; }
//============================================================================== void OldSchoolLookAndFeel::drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour, bool isMouseOverButton, bool isButtonDown) { const int width = button.getWidth(); const int height = button.getHeight(); const float indent = 2.0f; const int cornerSize = jmin (roundToInt (width * 0.4f), roundToInt (height * 0.4f)); Path p; p.addRoundedRectangle (indent, indent, width - indent * 2.0f, height - indent * 2.0f, (float) cornerSize); Colour bc (backgroundColour.withMultipliedSaturation (0.3f)); if (isMouseOverButton) { if (isButtonDown) bc = bc.brighter(); else if (bc.getBrightness() > 0.5f) bc = bc.darker (0.1f); else bc = bc.brighter (0.1f); } g.setColour (bc); g.fillPath (p); g.setColour (bc.contrasting().withAlpha ((isMouseOverButton) ? 0.6f : 0.4f)); g.strokePath (p, PathStrokeType ((isMouseOverButton) ? 2.0f : 1.4f)); }
void drawRotarySlider (Graphics& g, int x, int y, int width, int height, float sliderPos, float rotaryStartAngle, float rotaryEndAngle, Slider& slider) override { const float diameter = jmin (width, height) - 4.0f; const float radius = (diameter / 2.0f) * std::cos (float_Pi / 4.0f); const float centreX = x + width * 0.5f; const float centreY = y + height * 0.5f; const float rx = centreX - radius; const float ry = centreY - radius; const float rw = radius * 2.0f; const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle); const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled(); const Colour baseColour (slider.isEnabled() ? slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 0.8f : 1.0f) : Colour (0x80808080)); Rectangle<float> r (rx, ry, rw, rw); AffineTransform t (AffineTransform::rotation (angle, r.getCentreX(), r.getCentreY())); float x1 = r.getTopLeft().getX(), y1 = r.getTopLeft().getY(), x2 = r.getBottomLeft().getX(), y2 = r.getBottomLeft().getY(); t.transformPoints (x1, y1, x2, y2); g.setGradientFill (ColourGradient (baseColour, x1, y1, baseColour.darker (0.1f), x2, y2, false)); Path knob; knob.addRectangle (r); g.fillPath (knob, t); Path needle; Rectangle<float> r2 (r * 0.1f); needle.addRectangle (r2.withPosition (Point<float> (r.getCentreX() - (r2.getWidth() / 2.0f), r.getY()))); g.setColour (slider.findColour (Slider::rotarySliderOutlineColourId)); g.fillPath (needle, AffineTransform::rotation (angle, r.getCentreX(), r.getCentreY())); }
void StupidFilterAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { const int numSamples = buffer.getNumSamples(); int channel, dp = 0; // This is the place where you'd normally do the guts of your plugin's // audio processing... for (channel = 0; channel < getNumInputChannels(); ++channel) { float* channelData = buffer.getSampleData (channel); float* delayData = delayBuffer.getSampleData (jmin (channel, delayBuffer.getNumChannels() - 1)); dp = delayPosition; for (int i = 0; i < numSamples; ++i) { const float in = channelData[i]; channelData[i] -= delayData[dp] + (std::real(coefB) * delayData[dp - 1]) + (std::real(coefC) * delayData[dp - 2]) + (std::real(coefD) * delayData[dp - 3]) + (std::real(coefE) * delayData[dp - 4]); delayData[dp] = (delayData[dp] + in) * delay; if (++dp >= delayBuffer.getNumSamples()) dp = 0; } } delayPosition = dp; // In case we have more outputs than inputs, we'll clear any output // channels that didn't contain input data, (because these aren't // guaranteed to be empty - they may contain garbage). for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) { buffer.clear (i, 0, buffer.getNumSamples()); } }
void createLayout (TextLayout& layout, const AttributedString& text, IDWriteFactory& directWriteFactory, IDWriteFontCollection& fontCollection, ID2D1DCRenderTarget& renderTarget) { ComSmartPtr<IDWriteTextLayout> dwTextLayout; if (! setupLayout (text, layout.getWidth(), layout.getHeight(), renderTarget, directWriteFactory, fontCollection, dwTextLayout)) return; UINT32 actualLineCount = 0; HRESULT hr = dwTextLayout->GetLineMetrics (nullptr, 0, &actualLineCount); layout.ensureStorageAllocated (actualLineCount); { ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text)); hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0); } HeapBlock<DWRITE_LINE_METRICS> dwLineMetrics (actualLineCount); hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount); int lastLocation = 0; const int numLines = jmin ((int) actualLineCount, layout.getNumLines()); float yAdjustment = 0; const float extraLineSpacing = text.getLineSpacing(); for (int i = 0; i < numLines; ++i) { TextLayout::Line& line = layout.getLine (i); line.stringRange = Range<int> (lastLocation, (int) lastLocation + dwLineMetrics[i].length); line.lineOrigin.y += yAdjustment; yAdjustment += extraLineSpacing; lastLocation += dwLineMetrics[i].length; } }
void GateTrigger::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { float threshold = library->getThreshold(); int64 releaseTicks = library->getReleaseTicks(); float velocityScale = library->getVelocityScale(); int windowSize = buffer.getNumSamples(); for (int i = 0; i < buffer.getNumSamples(); i += windowSize) { float rms = 0; for (int chan = 0; chan < buffer.getNumChannels(); chan++) { rms += buffer.getMagnitude (chan, i, jmin(windowSize, buffer.getNumSamples() - i)); } rms = rms / buffer.getNumChannels() * 100; if (rms - lastRms > threshold) { if (Time::getHighResolutionTicks() - lastTriggerTick > releaseTicks) { Pattern* pattern = sequencer->getPattern(); Instrument* instrument = pattern->getActiveInstrument(); // play note float velocity = (rms - lastRms) / velocityScale; DBG("RMS: " + String(rms) + " lastRMS: " + String(lastRms) + " velocity: " + String(velocity)); int noteNumber = instrument->getNoteNumber(); MidiMessage m = MidiMessage::noteOn (1, noteNumber, velocity); midiMessages.addEvent (m, i); // insert into sequencer pattern int step = round(sequencer->getPreciseStep()); step = step % pattern->getNumSteps(); Cell* cell = pattern->getCellAt (0, step); delayedInserterThread->insertNote (cell, velocity, instrument); // Retrigger the reset timer resetTimer->retrigger(); lastTriggerTick = Time::getHighResolutionTicks(); } } lastRms = rms; } }
Range<float> TextLayout::Line::getLineBoundsX() const noexcept { Range<float> range; bool isFirst = true; for (int i = runs.size(); --i >= 0;) { const Run* run = runs.getUnchecked(i); jassert (run != nullptr); if (run->glyphs.size() > 0) { float minX = run->glyphs.getReference(0).anchor.x; float maxX = minX; for (int j = run->glyphs.size(); --j > 0;) { const Glyph& glyph = run->glyphs.getReference (j); const float x = glyph.anchor.x; minX = jmin (minX, x); maxX = jmax (maxX, x + glyph.width); } if (isFirst) { isFirst = false; range = Range<float> (minX, maxX); } else { range = range.getUnionWith (Range<float> (minX, maxX)); } } } return range + lineOrigin.x; }
int read (char* destBuffer, int maxBytesToRead, int timeOutMilliseconds) { const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds); if (pipeIn == -1) { pipeIn = openPipe (createdPipe ? pipeInName : pipeOutName, O_RDWR | O_NONBLOCK, timeoutEnd); if (pipeIn == -1) return -1; } int bytesRead = 0; while (bytesRead < maxBytesToRead) { const int bytesThisTime = maxBytesToRead - bytesRead; const int numRead = (int) ::read (pipeIn, destBuffer, (size_t) bytesThisTime); if (numRead <= 0) { if (errno != EWOULDBLOCK || stopReadOperation || hasExpired (timeoutEnd)) return -1; const int maxWaitingTime = 30; waitForInput (pipeIn, timeoutEnd == 0 ? maxWaitingTime : jmin (maxWaitingTime, (int) (timeoutEnd - Time::getMillisecondCounter()))); continue; } bytesRead += numRead; destBuffer += numRead; } return bytesRead; }
void JucerDocumentEditor::addComponent (const int index) { showLayout(); if (ComponentLayoutPanel* const panel = dynamic_cast <ComponentLayoutPanel*> (tabbedComponent.getCurrentContentComponent())) { const Rectangle<int> area (panel->getComponentArea()); document->beginTransaction ("Add new " + ObjectTypes::componentTypeHandlers [index]->getTypeName()); const int randomness = jmin (80, area.getWidth() / 2, area.getHeight() / 2); int x = area.getWidth() / 2 + Random::getSystemRandom().nextInt (randomness) - randomness / 2; int y = area.getHeight() / 2 + Random::getSystemRandom().nextInt (randomness) - randomness / 2; x = document->snapPosition (x); y = document->snapPosition (y); panel->xyToTargetXY (x, y); if (Component* newOne = panel->layout.addNewComponent (ObjectTypes::componentTypeHandlers [index], x, y)) panel->layout.getSelectedSet().selectOnly (newOne); document->beginTransaction(); } }
void removeColumn() override { if (auto* p = owner.getAudioProcessor()) { if (p->getBusCount (isInput) > 1 && p->canRemoveBus (isInput)) { if (p->removeBus (isInput)) { currentBus = jmin (p->getBusCount (isInput) - 1, currentBus); updateBusButtons(); updateBusLayout(); if (auto* config = owner.getConfig (! isInput)) { config->updateBusButtons(); config->updateBusLayout(); } owner.update(); } } } }
void MyLookAndFeel::drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) { const int tickWidth = jmin (20, button.getHeight() - 4); drawTickBox (g, button, 4, (button.getHeight() - tickWidth) / 2, tickWidth, tickWidth, button.getToggleState(), button.isEnabled(), isMouseOverButton, isButtonDown); g.setColour (button.findColour (ToggleButton::textColourId)); g.setFont (*Topaz); const int textX = tickWidth + 5; g.drawFittedText (button.getButtonText(), textX, 4, button.getWidth() - textX - 2, button.getHeight() - 8, Justification::centredLeft, 10); }
void LoudnessBar::valueChanged (Value & value) { if (value == levelValue) { currentLevel = value.getValue(); // Ensure that the currentLevel is in the interval // [minimumLevel, maximumLevel]. currentLevel = jmax(currentLevel, float(minLoudness.getValue())); currentLevel = jmin(currentLevel, float(maxLoudness.getValue())); if (currentLevel != previousLevel) { // float topBorderInPercent = stretch*jmax(currentLevel,previousLevel) + offset; // float bottomBorderInPercent = stretch*jmin(currentLevel,previousLevel) + offset; // // const int topLeftX = 0; // const int topLeftY = floor((1-topBorderInPercent) * (float) getHeight()) -3; // const int heightOfSectionToDraw = ceil((topBorderInPercent-bottomBorderInPercent) * (float) getHeight()) + 3; // previousLevel = currentLevel; // // repaint(topLeftX, topLeftY, getWidth(), heightOfSectionToDraw); // Mesurements showed that it is more CPU efficient to draw the whole // bar and not only the section that has changed. repaint(); } } else if (value == minLoudness || value == maxLoudness) { determineStretchAndOffset(); repaint(); } }
//============================================================================== void NonShinyLookAndFeel::drawShinyButtonShape (Graphics& g, float x, float y, float w, float h, float maxCornerSize, const Colour& baseColour, const float strokeWidth, const bool flatOnLeft, const bool flatOnRight, const bool flatOnTop, const bool flatOnBottom) throw() { if (w <= strokeWidth * 1.1f || h <= strokeWidth * 1.1f) return; const float cs = jmin (maxCornerSize, w * 0.5f, h * 0.5f); Path outline; createRoundedPath (outline, x, y, w, h, cs, ! (flatOnLeft || flatOnTop), ! (flatOnRight || flatOnTop), ! (flatOnLeft || flatOnBottom), ! (flatOnRight || flatOnBottom)); ColourGradient cg (baseColour, 0.0f, y, baseColour.overlaidWith (Colour (0x070000ff)), 0.0f, y + h, false); cg.addColour (0.5, baseColour.overlaidWith (Colour (0x25ffffff))); cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff))); //g.setGradientFill (cg); g.setColour(baseColour); g.fillPath (outline); g.setColour (Colour (0x80000000)); g.strokePath (outline, PathStrokeType (strokeWidth)); }
//============================================================================== VstPluginWindowTabPanel::VstPluginWindowTabPanel (PluginEditorWindowHolder* owner_, BasePlugin* plugin_, VstPluginWindow* window_, VstPluginWindowContent* content_, VstPluginNativeEditor* nativeEditor_, VstPluginExternalEditor* externalEditor_) : TabbedComponent (TabbedButtonBar::TabsAtBottom), owner (owner_), plugin (plugin_), window (window_), content (content_), nativeEditor (nativeEditor_), externalEditor (externalEditor_), viewport (0) { DBG ("VstPluginWindowTabPanel::VstPluginWindowTabPanel"); Colour backgroundColour = window->getBackgroundColour (); int lastSelectedTab = plugin->getIntValue (PROP_WINDOWPAGE, 0); // external GUI if (externalEditor) addTab (T("Interface"), backgroundColour, externalEditor, true); // native GUI if (nativeEditor) { viewport = new Viewport (String::empty); viewport->setScrollBarsShown (true, false); viewport->setViewedComponent (nativeEditor); addTab (T("Parameters"), backgroundColour, viewport, true); } // change last saved tab setCurrentTabIndex (jmax (0, jmin (1, lastSelectedTab))); }
//====================================================================== void HeaderComponent::resized() { auto bounds = getLocalBounds(); configLabel.setFont ({ bounds.getHeight() / 3.0f }); //====================================================================== { auto headerBounds = bounds.removeFromLeft (tabsWidth); const int buttonSize = 25; auto buttonBounds = headerBounds.removeFromRight (buttonSize); projectSettingsButton->setBounds (buttonBounds.removeFromBottom (buttonSize).reduced (2)); juceIcon->setBounds (headerBounds.removeFromLeft (headerBounds.getHeight()).reduced (2)); headerBounds.removeFromRight (5); projectNameLabel.setBounds (headerBounds); } //====================================================================== auto exporterWidth = jmin (400, bounds.getWidth() / 2); Rectangle<int> exporterBounds (0, 0, exporterWidth, bounds.getHeight()); exporterBounds.setCentre (bounds.getCentre()); runAppButton->setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2)); saveAndOpenInIDEButton->setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2)); exporterBounds.removeFromRight (5); exporterBox.setBounds (exporterBounds.removeFromBottom (roundToInt (exporterBounds.getHeight() / 1.8f))); configLabel.setBounds (exporterBounds); bounds.removeFromRight (5); userSettingsButton->setBounds (bounds.removeFromRight (bounds.getHeight()).reduced (2)); }
bool AudioFormatWriter::writeFromAudioSource (AudioSource& source, int numSamplesToRead, const int samplesPerBlock) { AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock); while (numSamplesToRead > 0) { const int numToDo = jmin (numSamplesToRead, samplesPerBlock); AudioSourceChannelInfo info; info.buffer = &tempBuffer; info.startSample = 0; info.numSamples = numToDo; info.clearActiveBufferRegion(); source.getNextAudioBlock (info); if (! writeFromAudioSampleBuffer (tempBuffer, 0, numToDo)) return false; numSamplesToRead -= numToDo; } return true; }
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) { jassert (isThisTheMessageThread()); // must only be called by the message thread const int64 endTime = Time::currentTimeMillis() + millisecondsToRunFor; while ((millisecondsToRunFor < 0 || endTime > Time::currentTimeMillis()) && ! quitMessageReceived) { JUCE_TRY { if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0)) { const int msToWait = (int) (endTime - Time::currentTimeMillis()); if (msToWait > 0) Thread::sleep (jmin (5, msToWait)); } } JUCE_CATCH_EXCEPTION } return ! quitMessageReceived; }
void DrawableButton::paintButton (Graphics& g, const bool isMouseOverButton, const bool isButtonDown) { if (style == ImageOnButtonBackground) { getLookAndFeel().drawButtonBackground (g, *this, findColour (getToggleState() ? TextButton::buttonOnColourId : TextButton::buttonColourId), isMouseOverButton, isButtonDown); } else { g.fillAll (findColour (getToggleState() ? backgroundOnColourId : backgroundColourId)); const int textH = (style == ImageAboveTextLabel) ? jmin (16, proportionOfHeight (0.25f)) : 0; if (textH > 0) { g.setFont ((float) textH); g.setColour (findColour (getToggleState() ? DrawableButton::textColourOnId : DrawableButton::textColourId) .withMultipliedAlpha (isEnabled() ? 1.0f : 0.4f)); g.drawFittedText (getButtonText(), 2, getHeight() - textH - 1, getWidth() - 4, textH, Justification::centred, 1); } } }
void drawDemo (Graphics& g) override { g.addTransform (getTransform()); const int rectSize = jmin (getWidth(), getHeight()) / 2 - 20; g.setColour (colour1.withAlpha (getAlpha())); g.fillRect (-rectSize, -rectSize, rectSize, rectSize); g.setGradientFill (ColourGradient (colour1, 10.0f, (float) -rectSize, colour2, 10.0f + rectSize, 0.0f, false)); g.setOpacity (getAlpha()); g.fillRect (10, -rectSize, rectSize, rectSize); g.setGradientFill (ColourGradient (colour1, rectSize * -0.5f, 10.0f + rectSize * 0.5f, colour2, 0, 10.0f + rectSize, true)); g.setOpacity (getAlpha()); g.fillRect (-rectSize, 10, rectSize, rectSize); g.setGradientFill (ColourGradient (colour1, 10.0f, 10.0f, colour2, 10.0f + rectSize, 10.0f + rectSize, false)); g.setOpacity (getAlpha()); g.drawRect (10, 10, rectSize, rectSize, 5); }
void VstPluginWindow::resizeContentComponent (const int width, const int height, const bool limitHeight) { DBG ("VstPluginWindow::resizeContentComponent"); int desiredWidth = width + 2 /* + getBorderThickness().getLeftAndRight ()*/; int desiredHeight = getTitleBarHeight() + getMenuBarHeight() + getBorderThickness().getTopAndBottom () + (content ? content->getTabbedPanelHeight () : 0) + (content ? (content->hasMidiKeyboardOpen() ? content->getMidiKeyboardHeight() : 0) : 0); int maxHeight = height + desiredHeight; maxHeight = limitHeight ? jmin (700, maxHeight) : maxHeight; setSize (desiredWidth, maxHeight); if (limitHeight) setResizeLimits (desiredWidth, desiredHeight, desiredWidth, maxHeight); }
//============================================================================== bool ComboBox::keyPressed (const KeyPress& key) { bool used = false; if (key.isKeyCode (KeyPress::upKey) || key.isKeyCode (KeyPress::leftKey)) { setSelectedItemIndex (jmax (0, getSelectedItemIndex() - 1)); used = true; } else if (key.isKeyCode (KeyPress::downKey) || key.isKeyCode (KeyPress::rightKey)) { setSelectedItemIndex (jmin (getSelectedItemIndex() + 1, getNumItems() - 1)); used = true; } else if (key.isKeyCode (KeyPress::returnKey)) { showPopup(); used = true; } return used; }
bool AudioFormatWriter::writeFromFloatArrays (const float* const* channels, int numSourceChannels, int numSamples) { if (numSamples <= 0) return true; if (isFloatingPoint()) return write ((const int**) channels, numSamples); int* chans[256]; int scratch[4096]; jassert (numSourceChannels < numElementsInArray (chans)); const int maxSamples = (int) (numElementsInArray (scratch) / numSourceChannels); for (int i = 0; i < numSourceChannels; ++i) chans[i] = scratch + (i * maxSamples); chans[numSourceChannels] = nullptr; int startSample = 0; while (numSamples > 0) { auto numToDo = jmin (numSamples, maxSamples); for (int i = 0; i < numSourceChannels; ++i) convertFloatsToInts (chans[i], channels[i] + startSample, numToDo); if (! write ((const int**) chans, numToDo)) return false; startSample += numToDo; numSamples -= numToDo; } return true; }
const Font OldSchoolLookAndFeel::getComboBoxFont (ComboBox& box) { Font f (jmin (15.0f, box.getHeight() * 0.85f)); f.setHorizontalScale (0.9f); return f; }
void OldSchoolLookAndFeel::drawLinearSlider (Graphics& g, int x, int y, int w, int h, float sliderPos, float minSliderPos, float maxSliderPos, const Slider::SliderStyle style, Slider& slider) { g.fillAll (slider.findColour (Slider::backgroundColourId)); if (style == Slider::LinearBar) { g.setColour (slider.findColour (Slider::thumbColourId)); g.fillRect (x, y, (int) sliderPos - x, h); g.setColour (slider.findColour (Slider::textBoxTextColourId).withMultipliedAlpha (0.5f)); g.drawRect (x, y, (int) sliderPos - x, h); } else { g.setColour (slider.findColour (Slider::trackColourId) .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.3f)); if (slider.isHorizontal()) { g.fillRect (x, y + roundToInt (h * 0.6f), w, roundToInt (h * 0.2f)); } else { g.fillRect (x + roundToInt (w * 0.5f - jmin (3.0f, w * 0.1f)), y, jmin (4, roundToInt (w * 0.2f)), h); } float alpha = 0.35f; if (slider.isEnabled()) alpha = slider.isMouseOverOrDragging() ? 1.0f : 0.7f; const Colour fill (slider.findColour (Slider::thumbColourId).withAlpha (alpha)); const Colour outline (Colours::black.withAlpha (slider.isEnabled() ? 0.7f : 0.35f)); if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical) { drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), minSliderPos, x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos - 7.0f, x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos, fill, outline); drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), maxSliderPos, x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos, x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos + 7.0f, fill, outline); } else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal) { drawTriangle (g, minSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), minSliderPos - 7.0f, y + h * 0.9f , minSliderPos, y + h * 0.9f, fill, outline); drawTriangle (g, maxSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), maxSliderPos, y + h * 0.9f, maxSliderPos + 7.0f, y + h * 0.9f, fill, outline); } if (style == Slider::LinearHorizontal || style == Slider::ThreeValueHorizontal) { drawTriangle (g, sliderPos, y + h * 0.9f, sliderPos - 7.0f, y + h * 0.2f, sliderPos + 7.0f, y + h * 0.2f, fill, outline); } else if (style == Slider::LinearVertical || style == Slider::ThreeValueVertical) { drawTriangle (g, x + w * 0.5f - jmin (4.0f, w * 0.3f), sliderPos, x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos - 7.0f, x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos + 7.0f, fill, outline); } } }
void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { double localRatio; { const SpinLock::ScopedLockType sl (ratioLock); localRatio = ratio; } if (lastRatio != localRatio) { createLowPass (localRatio); lastRatio = localRatio; } const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 3; int bufferSize = buffer.getNumSamples(); if (bufferSize < sampsNeeded + 8) { bufferPos %= bufferSize; bufferSize = sampsNeeded + 32; buffer.setSize (buffer.getNumChannels(), bufferSize, true, true); } bufferPos %= bufferSize; int endOfBufferPos = bufferPos + sampsInBuffer; const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels()); while (sampsNeeded > sampsInBuffer) { endOfBufferPos %= bufferSize; int numToDo = jmin (sampsNeeded - sampsInBuffer, bufferSize - endOfBufferPos); AudioSourceChannelInfo readInfo (&buffer, endOfBufferPos, numToDo); input->getNextAudioBlock (readInfo); if (localRatio > 1.0001) { // for down-sampling, pre-apply the filter.. for (int i = channelsToProcess; --i >= 0;) applyFilter (buffer.getWritePointer (i, endOfBufferPos), numToDo, filterStates[i]); } sampsInBuffer += numToDo; endOfBufferPos += numToDo; } for (int channel = 0; channel < channelsToProcess; ++channel) { destBuffers[channel] = info.buffer->getWritePointer (channel, info.startSample); srcBuffers[channel] = buffer.getReadPointer (channel); } int nextPos = (bufferPos + 1) % bufferSize; for (int m = info.numSamples; --m >= 0;) { jassert (sampsInBuffer > 0 && nextPos != endOfBufferPos); const float alpha = (float) subSampleOffset; for (int channel = 0; channel < channelsToProcess; ++channel) *destBuffers[channel]++ = srcBuffers[channel][bufferPos] + alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]); subSampleOffset += localRatio; while (subSampleOffset >= 1.0) { if (++bufferPos >= bufferSize) bufferPos = 0; --sampsInBuffer; nextPos = (bufferPos + 1) % bufferSize; subSampleOffset -= 1.0; } } if (localRatio < 0.9999) { // for up-sampling, apply the filter after transposing.. for (int i = channelsToProcess; --i >= 0;) applyFilter (info.buffer->getWritePointer (i, info.startSample), info.numSamples, filterStates[i]); } else if (localRatio <= 1.0001 && info.numSamples > 0) { // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities for (int i = channelsToProcess; --i >= 0;) { const float* const endOfBuffer = info.buffer->getReadPointer (i, info.startSample + info.numSamples - 1); FilterState& fs = filterStates[i]; if (info.numSamples > 1) { fs.y2 = fs.x2 = *(endOfBuffer - 1); } else { fs.y2 = fs.y1; fs.x2 = fs.x1; } fs.y1 = fs.x1 = *endOfBuffer; } } jassert (sampsInBuffer >= 0); }