<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ELAVARASAN SHANKAR</title>
    <description>The latest articles on DEV Community by ELAVARASAN SHANKAR (@elavarasan_shankar_d8cfcf).</description>
    <link>https://dev.to/elavarasan_shankar_d8cfcf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3980391%2F13e743a0-ab09-41ac-b8e0-110096e9299b.jpg</url>
      <title>DEV Community: ELAVARASAN SHANKAR</title>
      <link>https://dev.to/elavarasan_shankar_d8cfcf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elavarasan_shankar_d8cfcf"/>
    <language>en</language>
    <item>
      <title>How I Built a Prompt-to-Music AI Agent &amp; Browser-Based Karaoke Separator with React &amp; ONNX</title>
      <dc:creator>ELAVARASAN SHANKAR</dc:creator>
      <pubDate>Fri, 12 Jun 2026 03:12:51 +0000</pubDate>
      <link>https://dev.to/elavarasan_shankar_d8cfcf/how-i-built-a-prompt-to-music-ai-agent-browser-based-karaoke-separator-with-react-onnx-12j3</link>
      <guid>https://dev.to/elavarasan_shankar_d8cfcf/how-i-built-a-prompt-to-music-ai-agent-browser-based-karaoke-separator-with-react-onnx-12j3</guid>
      <description>&lt;p&gt;Tags: react, webdev, onnx, audio&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Music generation, vocal separation, and intelligent arrangement have traditionally been server-side tasks requiring complex pipelines and expensive GPU clusters. But what if we could bring the entire interactive music-creation experience — &lt;strong&gt;real-time preview&lt;/strong&gt;, &lt;strong&gt;offline export&lt;/strong&gt;, &lt;strong&gt;prompt-based AI music generation&lt;/strong&gt;, and &lt;strong&gt;local karaoke processing&lt;/strong&gt; — directly into the browser?&lt;/p&gt;

&lt;p&gt;In this post, I'll share how I built &lt;strong&gt;Rapid AI Studio&lt;/strong&gt;, a client-side React and Tone.js application featuring:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A Prompt-to-Music AI Agent:&lt;/strong&gt; Enter any prompt (e.g., &lt;em&gt;"Create an energetic Tamil Kuthu beat with a driving bassline and a Nadaswaram melody"&lt;/em&gt;), and the agent composes and adds the tracks directly to the arrangement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Client-Side Karaoke Separator:&lt;/strong&gt; Runs a local neural network with &lt;strong&gt;84% accuracy&lt;/strong&gt; using &lt;strong&gt;ONNX Runtime Web&lt;/strong&gt; to separate vocals and accompaniment locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-Performance Audio Engine:&lt;/strong&gt; Tone.js scheduling, synth fallbacks, and real-time playback.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend UI:&lt;/strong&gt; React + TypeScript + Tailwind CSS for a premium, glassmorphic dark-mode interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio Engine:&lt;/strong&gt; &lt;strong&gt;Tone.js v15&lt;/strong&gt; (built on top of the Web Audio API) for sample playback, precise timing scheduling, and synthesis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client-Side AI:&lt;/strong&gt; &lt;strong&gt;ONNX Runtime Web (&lt;code&gt;onnxruntime-web&lt;/code&gt;)&lt;/strong&gt; executing a local neural network with &lt;strong&gt;84% accuracy&lt;/strong&gt; for vocal/accompaniment separation (Karaoke mode).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Music Agent:&lt;/strong&gt; A natural-language agent interface that takes user prompts to compose MIDI sequences, beats, harmony, and arrangements in real time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline Rendering:&lt;/strong&gt; &lt;code&gt;OfflineAudioContext&lt;/code&gt; for high-speed, non-realtime rendering of arrangements straight to &lt;code&gt;.wav&lt;/code&gt; files.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 The Prompt-to-Music AI Agent
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;Rapid AI Studio&lt;/strong&gt;, users don't need to be music-theory experts. They simply write what they want to hear.&lt;/p&gt;

&lt;p&gt;The AI Agent interprets the prompt and generates a multi-track composition containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Groove &amp;amp; Beats:&lt;/strong&gt; Automatically maps drum samples and rhythmic patterns (e.g. Parai drum, Pambai hits for Kuthu).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Melody &amp;amp; Harmony:&lt;/strong&gt; Dynamically selects matching lead instruments (like &lt;em&gt;Nadaswaram&lt;/em&gt;) and harmony instruments (like &lt;em&gt;Veena&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Arrangement:&lt;/strong&gt; Generates MIDI notes, velocities, and durations, and inserts them directly as tracks into the playback engine.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎤 High-Performance AI: Client-Side Karaoke with ONNX Runtime Web
&lt;/h2&gt;

&lt;p&gt;Instead of sending audio files to a cloud server to extract vocals or create karaoke tracks, &lt;strong&gt;Rapid AI Studio&lt;/strong&gt; performs the separation locally in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;We compile our vocal-separation neural network to the ONNX format and run it client-side using &lt;code&gt;onnxruntime-web&lt;/code&gt; and WebAssembly (WASM) with SIMD acceleration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;84% Accuracy:&lt;/strong&gt; Performs state-of-the-art separation on the fly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Backend Costs:&lt;/strong&gt; By offloading inference to the user's browser, there are no expensive GPU servers to pay for or maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% Privacy:&lt;/strong&gt; Since audio files never leave the user's device, their recordings and tracks remain completely private.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initializing the local ONNX session for vocal separation&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ort&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;onnxruntime-web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InferenceSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/assets/vocal_separator.onnx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;executionProviders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wasm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;enableCpuMemArena&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;enableMemPattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Technical Challenge 1: The "Treble Collapse" and FM Aliasing
&lt;/h2&gt;

&lt;p&gt;During development, we noticed that when sample files failed to load due to cache issues or slow network connections, the synthetic fallback synthesizer for lead instruments (like the Nadaswaram) played with extreme digital noise, distortion, and a "treble collapse" sound.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Cause:&lt;/strong&gt; the live-preview fallback instrument was originally defined using &lt;code&gt;Tone.FMSynth&lt;/code&gt; with a sawtooth carrier wave modulated by a sine modulator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Tone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PolySynth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Tone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FMSynth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;oscillator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sawtooth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;harmonicity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;modulationIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;3.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While FM synthesis sounds great with simple waves (like sine or triangle), applying frequency modulation to a sawtooth wave (which has infinite high-frequency harmonics) causes severe digital aliasing and clipping. The shifted harmonics fold back below the Nyquist frequency, creating harsh digital noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; we refactored the preview fallback to use a clean subtractive &lt;code&gt;Tone.Synth&lt;/code&gt; with a sawtooth oscillator, bypassing FM worklet limitations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Tone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PolySynth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Tone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Synth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;oscillator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sawtooth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;attack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;decay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sustain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This matched our offline export engine perfectly and instantly restored a warm, clean lead-melody sound.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Challenge 2: Upgrading Fallback Players Asynchronously
&lt;/h2&gt;

&lt;p&gt;When a user loads the app, sample downloads are triggered asynchronously. If a user starts playing before samples finish downloading, the engine falls back to the synthetic instruments.&lt;/p&gt;

&lt;p&gt;However, we found that once a synthetic player was cached in the active track map (&lt;code&gt;playersMap&lt;/code&gt;), it would never get replaced — even after the samples finished downloading in the background. The user was stuck listening to the synth, even though the high-quality samples were now fully loaded in memory!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; we implemented an automatic upgrade checker inside our state-synchronization loop (&lt;code&gt;syncState&lt;/code&gt;). Every time the track arrangement changes or the user interacts with playback, the engine checks if the active player is a synthetic fallback (&lt;code&gt;Tone.PolySynth&lt;/code&gt;) but its corresponding sample buffers have now successfully loaded in the cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If the player is currently synthetic, but samples have loaded in the background, reload the track!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playersMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPlayer&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;currentPlayer&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Tone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PolySynth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;INSTRUMENT_DATA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instrumentId&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasLoadedBuffers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kurl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;normalizeStorageUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kurl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kurl&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasLoadedBuffers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;changedExistingIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Forces re-instantiation as a Tone.Sampler!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This dynamically swaps out synthetic synths for high-quality multi-samplers on the fly, with zero interruption to the user experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion &amp;amp; Try It Out!
&lt;/h2&gt;

&lt;p&gt;Building an audio workstation on top of the Web Audio API requires balancing CPU budgets, network latency, and synthesis algorithms. By combining Tone.js, smart preloading, local ONNX neural networks for karaoke vocal separation, a prompt-to-music AI Agent, and dynamic fallback-to-sampler upgrades, you can deliver a premium, desktop-grade audio production experience directly in a standard web browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rapid AI Studio&lt;/strong&gt; — make music in minutes, free, in your browser or on Android.&lt;/p&gt;

&lt;h3&gt;
  
  
  👉 Try it &amp;amp; follow along
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🎧 &lt;strong&gt;Web app:&lt;/strong&gt; &lt;a href="https://rapidaiaudiostudio.com/" rel="noopener noreferrer"&gt;https://rapidaiaudiostudio.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📱 &lt;strong&gt;Android (Google Play):&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.rapid.aistudio" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.rapid.aistudio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;▶️ &lt;strong&gt;YouTube:&lt;/strong&gt; &lt;a href="https://www.youtube.com/@rapidaiaudiostudio" rel="noopener noreferrer"&gt;https://www.youtube.com/@rapidaiaudiostudio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📘 &lt;strong&gt;Facebook:&lt;/strong&gt; &lt;a href="https://www.facebook.com/Rapidaistudio" rel="noopener noreferrer"&gt;https://www.facebook.com/Rapidaistudio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🚀 &lt;strong&gt;Product Hunt:&lt;/strong&gt; &lt;a href="https://www.producthunt.com/products/rapid-ai-studio" rel="noopener noreferrer"&gt;https://www.producthunt.com/products/rapid-ai-studio&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💻 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/shankarelavarasan/rapid-ai-audio-studio" rel="noopener noreferrer"&gt;https://github.com/shankarelavarasan/rapid-ai-audio-studio&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>react</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
