Roger B. Dannenberg

Home Publications Videos Opera Audacity
Dannenberg playing trumpet.
Photo by Alisa.

Controlling Soundcool with a Web Browser Using O2host


Summary

O2host provides a simple way to connect browsers and microcontrollers to OSC, MIDI, and other browsers and microcontrollers. This installment shows how the o2host program can be used to connect image recognition software running in a browser to sound synthesis software (Soundcool). The key is to use o2host as an intermediary that can communicate with both browsers and OSC-enabled programs like Soundcool.

About the Author

Roger B. Dannenberg is Emeritus Professor of Computer Science at Carnegie Mellon University and a Fellow of the Association for Computing Machinery. He is known for a broad range of research in Computer Music, including the creation of interactive computer accompaniment systems, languages for computer music, music understanding systems, and music composing software. He is a co-creator of Audacity, perhaps the most widely used music editing software.

Additional References

O2 source code is open and free.

A video prepared for ICMC 2022 demonstrates location independence and discovery features of O2.

Building Music Systems with O2 and O2lite is an introduction to O2.

Using O2host with O2lite and MicroPython is the first article in this series on o2host.

Articles on O2 are listed in my bibliography.

The o2host program can act as a simple web server among other things. Browsers that load pages from o2host can open a Web Socket and exchange O2 messages. This allows web browsers to communicate with other O2 processes, even though browsers do not have direct general access to network sockets, nor can they run the O2 protocol directly over TCP/IP network protocols.

In this blog, I will describe a little application that uses Handtrack.js to track hands and gestures using a webcam. Handtrack runs in Javascript in a browser. We will use Handtrack to control sounds created with Soundcool, an easy-to-use, interactive, modular computer music system. To get from the browser to Soundcool, we will use o2host as an intermediary (see Figure 1). The data flow is as follows: When a gesture is recognized and it is time to send an action to Soundcool, code in the browser sends an O2 message over a Web Socket to o2host. From there, the message is converted to OSC (Open Sound Control) and forwarded to Soundcool.

Figure 1. Messages from the browser running Handtrack.js are sent as O2 messages over a Web Socket to o2host and from there are forwarded as OSC messages to the Soundcool process.

Demonstration Video

Here is what the system looks like when everything is running. The video analysis frame rate is low in the video because I was also running a screen capture program.

Implementation

The entire project is open and free to inspect, including the o2host program, which is part of the O2 system, which is shared on Github. Sources for this project are here.

To run the Handtrack code, I used examples as a guide. Here's what the main analysis process looks like:

function runDetection() {
    model.detect(video).then(predictions => {
        send_predictions(predictions);
        video.style.height = 240;
        model.renderPredictions(predictions, canvas, context, video);
        if (isVideo) {
            requestAnimationFrame(runDetection);
        }
    });
}
  

When an analysis is complete, send_predictions() is called with a list of descriptors for every object identified, e.g. there could be a face and an pinch gesture in the image. The implementation of send_predictions() has a lot of logic to determine when to actually start a sound and to decide which sound to play. The following has that logic replaced by ... in order to highlight the use of O2. o2ws_send sends an O2 message over the web socket protocol. The address will be something like "/sndcues/4/push2" which consists of an O2 service ("sndcues") followed by a complete OSC address ("/4/push2", used as the OSC address when we forward sndcues to an OSC URL and port number.) The other parameters you see are a timestamp (0 means now), the type string ("f" for float), and the value (1.0). Normally, the touchscreen app that sends OSC to Soundcool sends a 1.0 when a control is pushed, and a 0.0 when the control is released, so in this code, I send 0.0 to the same address after a 250 ms delay.

function send_predictions(predictions) {
    for (p of predictions) {
        ...
        if ((p.class == PINCH || p.class == POINT) &&
            ...
            o2ws_send(address, 0, "f", 1.0);
            setTimeout(() => { o2ws_send(address, 0, "f", 0.0); }, 250);
            ...
        }
    }
}

To make this all work, we need to serve the web pages to the browser and forward O2 messages to OSC. This is done by running the o2host program and configuring it to forward the sndcues service to OSC port 8001, and the drumloop service to OSC port 8002, both at 127.0.0.1 (the same machine). The o2host configuration looks like this:

--------------------------------------------------------------------------------
Configuration: handtrack             Load   Delete 
    Rename to:                       Save   New 

Ensemble name:     rbdhttest                         Polling rate: 500 
Debug flags:       rsq                               Reference Clock: Y
Networking (up/down to select): local network      
HTTP Port: 8080  Root: www                            
MQTT Host:                                  MQTT Port:      
Fwd Service sndcues              to OSC IP 127.000.000.001 Port 8001  UDP (X )
Fwd Service drumloop             to OSC IP 127.000.000.001 Port 8002  UDP (X )

················································································
New forward O2 to OSC:          New forward OSC to O2:  
New MIDI In to O2:      New MIDI Out from O2:      MIDI Refresh:  
Type ESC to start, Control-H for Help.
--------------------------------------------------------------------------------

Be sure to run o2host in the directory containing the www directory so that it can find and serve the web pages.

Finally, you'll need to configure Soundcool. There is a scconfig.soundcool file in the sources zip file that you can load, although you will have to reload the sound files (also included) because the files are stored in scconfig.soundcool using complete paths that will be different on your machine.

Summary

This post shows how you can use the o2host program to deliver messages from browsers to any OSC-enabled program like Soundcool. O2 supports an approach to building systems in a modular fashion, using multiple application programs with high functionality and controlling them through a flexible messaging system (O2).

Let me know if you need help with O2 or getting this example to work.

Additional references appear in the left sidebar (scroll up).