unkleho / reactronica Goto Github PK
View Code? Open in Web Editor NEWReact audio components for making music in the browser
Home Page: https://reactronica.com
License: MIT License
React audio components for making music in the browser
Home Page: https://reactronica.com
License: MIT License
When attempting to play sounds on Safari iOS from this app, no sounds can be heard. Opening the same website in Chrome for desktop plays the sounds correctly, but there are some errors in the console related to AudioContext:
There's a Tone.js issue open and appears to affect safari and some other browsers.
Edit: Testing the piano roll example from the documentation page also results in silence when using safari iOS (but works great on Chrome desktop). I haven't been able to test from Android yet.
I saw this project demoed at nextjs conf and it looks awesome, can't wait to try it out.
I was curious if there is a way to export a given Song
component (and all of its children) to a sound file (i.e. .mp3
). If not officially supported, do you have any suggestions for how to go from react components to file export?
First off, I wanted to say thank you for building out this awesome library! I stumbled upon ToneJS first and figured I was going to have to build out similar abstractions for interacting with that API in React, so I'm thankful that most of the heavy lifting has been done here already.
One issue that I just spent a lot of time trying to debug was why a song with a track and sampler instrument would throw errors as soon as it attempted to play a note. I had sent through a samples
prop with notes and file URLs in the structure shown in the docs...
<Instrument
samples={{
"C-2": "...",
"C#-2": "...",
}}
type="sampler" />
Any time I change isPlaying
to true
for the <Song />
, it would throw this error:
Uncaught Error: No available buffers for note: -12
at s.default.Sampler._findClosest (Tone.js:7)
at s.default.Sampler.triggerAttack (Tone.js:7)
at s.default.Sampler.triggerAttackRelease (Tone.js:7)
at Track.tsx:95
at Array.map (<anonymous>)
at Track.tsx:94
at Array.forEach (<anonymous>)
at s.default.Sequence.callback (Track.tsx:93)
at s.default.Sequence.s.default.Part._tick (Tone.js:7)
at s.default.Event._tick (Tone.js:7)
at s.default.TransportRepeatEvent.s.default.TransportEvent.invoke (Tone.js:7)
at s.default.TransportRepeatEvent.invoke (Tone.js:7)
at s.default.TransportEvent.invoke (Tone.js:7)
at s.default.Timeline.<anonymous> (Tone.js:7)
at s.default.Timeline.<anonymous> (Tone.js:7)
at s.default.Timeline.<anonymous> (Tone.js:7)
at Array.forEach (<anonymous>)
at s.default.Timeline._iterate (Tone.js:7)
at s.default.Timeline.forEachAtTime (Tone.js:7)
at s.default.Transport._processTick (Tone.js:7)
at s.default.Clock.<anonymous> (Tone.js:7)
at s.default.TickSource.forEachTickBetween (Tone.js:7)
at s.default.Clock._loop (Tone.js:7)
at s.default.Context.s.default.Emitter.emit (Tone.js:7)
After some more trial and error, I realized from the network tab in dev tools that samples weren't actually being loaded. Once the onLoad
function was provided, network requests were firing off to load the resources and then it would play as expected.
At the very least, there should be a JSDoc comment that notes this function is required when providing type="sampler"
. It would be even better if we could use conditional types to require this property when type
is passed through as "sampler"
.
Hello, thank you for creating this library I've been wrestling with using MIDI in the browser with Tonejs for months and I've been much more productive since adding this library. I was wondering is the DAW Example on the website open source as well? I'm trying to build out a MIDI player that's slightly more complicated than the examples and having a reference would be very helpful.
Hi there,
Hoping to have some extra direction here. I programmed a simple drum beat in plain ToneJS using the Loop
API, and I'm having some trouble converting the pattern over to a composition of Reactronica
components. Here's a live site with what the loop sounds like: https://tonejs-pattern--beets.netlify.app/
The code for this in ToneJS looks like this:
import { Loop } from "tone";
import * as Tone from "tone";
Tone.Transport.bpm.value = CoreUtils.randomInt(75, 85);
Tone.Transport.swing = CoreUtils.randomFloat(0.25, 0.3);
new Loop((time) => closedHiHat.start(time), "8n").start();
new Loop((time) => openHiHat.start(time), "1m").start("0:7");
new Loop((time) => kick.start(time), "1m").start();
new Loop((time) => kick.start(time), "1m").start("0:5");
new Loop((time) => snare.start(time), "2n").start("4n");
For samples that I want to play on as different note lengths (1/8 note, 1/2 note), do I need to render a new <Track />
with the subdivision
prop?
Here's what I currently have, but it sounds a little bit off, and I think I might be missing something. You can test how it sounds here: https://reactronica-experiment--beets.netlify.app/ and the code that's currently powering this is here: https://github.com/brandongregoryscott/beets/blob/reactronica-experiment/src/app.tsx#L6:L112
Any help is much appreciated ๐
Reactronica Synth - https://codesandbox.io/s/reactronica-synth-rfh3c?file=/src/Synth.js
Hi. The link above links to a Synth component that has some issues:
What am I doing wrong?
Hey there, not sure if this is on your roadmap or not, but I will have a use case for a wrapper around the Recorder
from ToneJS to export an audio file of the current song arrangement.
I'm not exactly sure what the API should look like just yet, but I figured I would document an issue and start discussion. I'm also happy to try to hack on something if no one else gets to it, either ๐
Hi, thanks for this great library.
Wonder if it's possible set playbackRate for sampler? https://tonejs.github.io/docs/14.7.39/Player.html#playbackRate
Great project! Would like to know what the plan for v1.0
What features or stability structure are you looking to add. I am asking because I plan to use it part of a project but I wouldn't want the APIs to drastically change by the time v1.0 rolls out.
๐ค
Description:
When using the Track component to build a step sequencer, I've noticed that after adding and deleting multiple notes on a step, some notes persist indefinitely. These residual notes continue playing even if they are no longer present in the steps prop array.
Steps to Reproduce:
Build a step sequencer using the Track component, and pass an array of notes into the steps prop.
Add and delete multiple notes on a particular step multiple times via an onClick function that adds and removes notes from the array that's passed into the Track components steps prop.
Observe that after a few iterations, some notes continue to play indefinitely.
Observations:
Notes will infinitely sustain if there are no successive notes present.
Sustaining notes can be interrupted if other notes on a successive step are present.
Logging out the array on each step reveals, that even if the steps prop array is empty, playback and infinite note sustain still occur.
This behaviour was also observed in the piano roll step sequencer example from the documentation.
Suspected Cause:
It seems that the Track component might be caching some notes and not updating them correctly after they are deleted multiple times. This is based on the observation that even with an empty steps prop array, playback and infinite note sustain still happens.
Additional Information:
I've built a sequencer setup that's functionally very similar to the one in the documentation, and this issue was consistent in both my own version and the example in the docs.
It looks like the <Track />
component is not properly removing or disposing of steps when props change. I ran into this on my own project using reactronica
, but I've reproduced the issue in a smaller sandbox environment: https://codesandbox.io/s/reactronica-42-step-duplication-bug-qnd8h?file=/src/App.tsx
To reproduce in the sandbox:
Play
button will be disabled until onLoad
runs)Track
which includes 4 hi-hat notes and a kick on the first step.I've patched the issue in a branch of my fork (85405d7) which I've tested against my project using reactronica, but not this sandbox example. I imagine it will resolve it, too, but I'm not 100% sure.
I'm trying to follow this example to use the PianoRoll, but I'm getting the following error:
Compiled with problems:
ERROR
src\SynthEngine.js
Line 25:10: 'PianoRoll' is not defined react/jsx-no-undef
Looking inside the Reactronica source I don't see a PianoRoll in the components.
Use more samples from WebudioFont
Listen to example at https://surikov.github.io/webaudiofont/examples/midiplayer.html
Can the oscillator and envelope values be changed on the fly like the effects values can? Or are they only set when the component re-renders? Here's a codesandbox of what I'm talking about - https://codesandbox.io/s/reactronica-synth-rfh3c. Thank you!
Even after using onload Buffer as well as the tone.js buffer component, the console still loads buffer is either not set or not loaded
. I've checked the network location and it does show that the .wav files have loaded, so is there something we should include in between?
<Song isPlaying={isPlaying} bpm={60}>
<Track steps={[(props.note)]}>
{/* <Instrument type="monoSynth" notes={['C3']} envelope={{attack: 0.2,release: 0.5,}} /> */}
<Instrument
type="sampler"
notes={notes}
samples={{
A0: "/public/piano/A0vH.wav",
B0: "/public/piano/B0vH.wav",,
}}
onLoad={(buffers) => {
// runs when all samples are loaded
}}
/>
</Track>
</Song>
Thank you!
It'd be awesome if you could share the code for your DAW (reactronica.com/daw) example as a reference. Thank you!
With my brief understanding of Tone.js, it would seem that Tone.Part
would allow users to play MidiNote
s that have a time
property as opposed to having everything be sequenced to a fixed tempo/time as provided by `Tone.Sequence.
Am I right in understanding that this is a current limitation of reactronica? Or am I not understanding Tone enough?
First of all, very nice project. so intuitive! great!
I have built a drum sequencer.
unfortunately, the timing here is not quite correct. the rhythm sounds a little out of sync, as if the note is not played exactly on the beat. actually, tonejs should trigger the sample exactly, but unfortunately it does not sound quite like that in your implementation. have you ever had problems with this?
export const App = () => {
const [playing, setPlaying] = useState(false);
const [isLoaded, setLoaded] = useState(false);
return (
<div>
<button disabled={!isLoaded} onClick={() => setPlaying(!playing)}>
play/pause
</button>
<Song isPlaying={playing}>
<Track
subdivision="8n"
steps={[
["C3", { name: "E3", velocity: 0.2 }],
[{ name: "E3", velocity: 0.05 }],
[{ name: "E3", velocity: 0.4 }],
[{ name: "E3", velocity: 0.05 }],
["D3", { name: "E3", velocity: 0.4 }],
[{ name: "E3", velocity: 0.1 }],
[{ name: "E3", velocity: 0.2 }],
[{ name: "E3", velocity: 0.05 }],
[{ name: "E3", velocity: 0.4 }],
[{ name: "E3", velocity: 0.1 }],
["C3", { name: "E3", velocity: 0.4 }],
[{ name: "E3", velocity: 0.05 }],
["D3", { name: "E3", velocity: 0.4 }],
[{ name: "E3", velocity: 0.05 }],
[{ name: "E3", velocity: 0.4 }],
[{ name: "E3", velocity: 0.05 }],
]}
>
<Instrument
type="sampler"
onLoad={() => setLoaded(true)}
samples={{
C3: "samples/drums/1/kick.wav",
D3: "samples/drums/1/snare.wav",
E3: "samples/drums/1/hat2.wav",
}}
/>
</Track>
</Song>
</div>
);
};
greetings, Jonathan :)
Here the samples:
samples.zip
Hi,
I stumbled over your repo. As I am the guy behind midi-bricks, I will consider integration of your components into my app. Is that a okay for you? By the way I am not making money with it.
https://github.com/TimSusa/cliptor
https://github.com/TimSusa/midi-bricks
Best Regards
Tim Susa
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.