Creating chip-tuned square & triangle wave sounds on web browsers with Blazor WebAssembly
Tags: blazor
Published: 2022-12-31 12:37:51

## "SoundMaker" Library

I found an interesting post in my Twitter timeline last month.

{% embed https://twitter.com/DTB_AutumnSky/status/1588806133275594752 %}

The tweet introduced a library that allows us to create chip-tuned square & triangle wave sounds and save them to a .wav file by **only C#**, "SoundMaker". (The GitHub repository URL is below.)

{% embed https://github.com/AutumnSky1010/SoundMaker#overview %}

The "SoundMaker" is distributed under the MIT license.

When I saw that tweet, one idea came to my mind. He said the "SoundMaker" is built on 100% pure C#. If it is true, **we should also be able to run the "SoundMaker" on web browsers powered by Blazor WebAssembly.** So I tried it.

## Implement it

There is [a simple example code](https://github.com/AutumnSky1010/SoundMaker#usage) on how to use the "SoundMaker" to create and save square & triangle wave sounds on the README document in the GitHub repository of the "SoundMaker". I created a new Blazor WebAssembly project and copied that example code, almost as is, into a `@code { ... }` code block of a Razor component file (.razor) in that Blazor WebAssembly project.

The outline of the code is like this:

```csharp
...
@code {
  private static string GenerateWavFile()
  {
    // Specify sound format, and generate sound waves.
    var soundFormat = new SoundFormat(SoundMaker.Sounds.SamplingFrequencyType.FourtyEightKHz, SoundMaker.Sounds.BitRateType.SixteenBit, SoundMaker.Sounds.ChannelType.Stereo);
    var wave = MakeStereoWave(soundFormat);

    // Save it into a file.
    var sound = new SoundWaveChunk(wave.GetBytes(soundFormat.BitRate));
    var waveFileFormat = new FormatChunk(SoundMaker.WaveFile.SamplingFrequencyType.FourtyEightKHz, SoundMaker.WaveFile.BitRateType.SixteenBit, SoundMaker.WaveFile.ChannelType.Stereo);
    var writer = new WaveWriter(waveFileFormat, sound);
    var filePath = "sample.wav";
    writer.Write(filePath);

    return filePath;
  }

  private static StereoWave MakeStereoWave(SoundFormat format)
  {
    // Number of quarter notes per minute.
    var tempo = 100;
    ...
    // can mix with StereoMixer class. 
    return new StereoMixer(channels).Mix();
  }
}
```

But, wait, wait.

If you look closely at the above code, you will find that **the program is doing a write to a file.** Here is an excerpt.


```csharp
private static string GenerateWavFile()
{
    // Save it into a file.
    ...
    var filePath = "sample.wav";
    writer.Write(filePath);
    ...
```

This program is a Blazor WebAssembly program that is loaded into a web browser and executed in its sandbox. So what happens when you do this **write to a local file**? Of course, it would not be written to the local storage of the device on which the web browser is actually running. So, would this process fail with an exception? That said, the `WaveWriter` class in the SoundMaker library apparently does not have the ability to write to an arbitrary `Stream`, and **there is no way to write a .wav file other than specifying the file path**. Is this that the "SoundMaker" library is not available on Blazor WebAssembly, unfortunately?

## Writing to local files in Blazor WebAssembly apps will be a success

In fact, **writing to local files in Blazor WebAssembly apps will be a success!**

Blazor WebAssembly uses Emscripten as its foundation to generate WebAssembly code generation, and because of this, the **on-memory filesystem simulation** (virtual file system) provided by Emscripten is also available in Blazor WebAssembly! (For more information, please refer to the following links.)

{% embed https://emscripten.org/docs/porting/files/file_systems_overview.html %}

Therefore, writing a .wav file into the local file system by the `WaveWriter` class in the "SoundMaker" library will be successful. The written file exists on the virtual file system in the web browser's WebAssembly process memory space. And, we can read the .wav file written to the virtual file system into an array of `byte`, and can do anything, such as playing back, downloading, etc., from the web browser.

## Real example

I've publicly pushed the Blazor WebAssembly project source code I explained above on the following GitHub repository.

{% embed https://github.com/sample-by-jsakamoto/Blazor-SoundMaker-on-BlazorWasm %}

And, this example has been deployed on GitHub Pages by a GitHub Actions script. You can try it immediately by following the next link.

{% embed https://sample-by-jsakamoto.github.io/Blazor-SoundMaker-on-BlazorWasm/ %}

The screenshot below shows how the above link looks when opened.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/ee91fbda-4972-bbe1-97cb-b4a1f6e5197f.png)

When you click the "Generate Sound and Play" button, the sound generated on the fly by the C# program I explained above will be played back. When you click the "Generate Sound and Download" button, the .wav file will be downloaded instead of playing back it. Please remember the generating sound process runs on your web browser! I confirmed that the example site can also be run on Apple mobile devices. **I could generate the chip-tuned sound with that example site and play it on my iPhone SE2.** That's amazing!

Moreover, as I already mentioned above, due to the source code of the example site being hosted on the GitHub repository, when you create a new "GitHub Codespace" for this repository, like the following screenshot,

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/3cfe6d2e-3e8f-7b07-52aa-35e28b45dc6b.png)

As shown in the screenshot below, **you can edit and run the code ("dotnet run" command execution) of this example site in a web browser immediately, without the need to set up a local development environment on your PC!**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/d47d7be1-e897-9857-c03e-8fdab99d431e.png)

## Conclusion

Now you can easily enjoy chip-tuned sound generation programming with "SoundMaker" anytime, anywhere, as long as you are connected to the Internet and use any device that supports GitHub Codespaces! That's really amazing!  

Thanks to the author of the "SoundMaker", [AutumnSky1010](https://github.com/AutumnSky1010), for publishing such a great library as an Open Source!

_Happy Coding :)_