gogins / csound-extended

Extensions for Csound including algorithmic composition, Android app, and WebAssembly.
GNU Lesser General Public License v2.1
40 stars 1 forks source link

Enable unified set of Csound for JavaScript examples to work on all platforms with csound_loader.js. #133

Closed gogins closed 4 years ago

gogins commented 4 years ago

Enable csound_loader.js to load and instantiate Csound with a JavaScript interface, the same or very similar on all platforms, for a set of example/test pieces:

WebAssembly (now built only based on AudioWorklet)

NW.js (csound.node bypasses browser audio, uses low-level Csound audio directly)

Android (no message callback, needed to use -odac -idac without -+rtaudio.

CsoundQt (newlook branch) HTML5 support basically works, yet on reflection, I am not testing these. The API functions are camel case, it is hard to get the code to run, it doesn't print Csound messages to the API callback, and it may leave CsoundQt hanging and in need of manually killing both CsoundQt and the WebEngine helper processes. Of course, if just WebAudio is used (edit csound_loader.js not to use injected csound), they probably all work as well as in any other browser.

gogins commented 4 years ago

Currently the loader assumes that the WebAssembly files are present in the environment. I will not change that at this time.

gogins commented 4 years ago

On my computer, the AudioWorklet implementation of Csound works fine with just ALSA and no PulseAudio, while csound.node running in NW.js crashes with just ALSA but runs fine with PulseAudio. I had to reconfigure PulseAudio to default to 48 KHz frames per second and float samples for that to work.

I would prefer an ALSA setup that supports all my platforms on this computer, failing that I would prefer a PulseAudio setup in which CsoundAudioNode works well.

gogins commented 4 years ago

I thought my HDMI monitor had speakers, but although the video is very good, it does not have speakers or, if it does, they are not working with my computer. The headphone jack, however, does work.

I will try changing my audio input and output code in CsoundAudioNode.Start to parse N from dacN and use that to index into the list of enumerated devices, rather than or in addition to trying to obtain a mic from the navigator.

No, I can't find out how to do that.

But now, I'm getting the navigator mic connecting (don't yet know if it actually works) to the USB audio. This is with the PulseAudio daemon running. The audio output is back to being full of crackles.

Perhaps audio is not routed from the USB device to the navigator without PulseAudio?

gogins commented 4 years ago

With PulseAudio:

0 audioinput: Default
1 audioinput: EDIROL UA-25EX (Advanced mode) Analog Stereo
2 audiooutput: Default
3 audiooutput: Built-in Audio Digital Stereo (HDMI 2)
4 audiooutput: EDIROL UA-25EX (Advanced mode) Analog Stereo

With no PulseAudio, just ALSA:

0.00 audioinput: Default
1.00 audioinput: UA-25EX, USB Audio-Default Audio Device
2.00 audioinput: UA-25EX, USB Audio-Front speakers
3.00 audioinput: UA-25EX, USB Audio-IEC958 (S/PDIF) Digital Audio Output
4.00 audioinput: UA-25EX, USB Audio-Direct sample snooping device
5.00 audioinput: UA-25EX, USB Audio-Direct hardware device without any conversions
6.00 audioinput: UA-25EX, USB Audio-Hardware device with all software conversions
7.00 audiooutput: Default
8.00 audiooutput: HDA Intel PCH, HDMI 0-Hardware device with all software conversions
9.00 audiooutput: HDA Intel PCH, HDMI 1-Hardware device with all software conversions
10.0 audiooutput: HDA Intel PCH, HDMI 2-Hardware device with all software conversions
11.0 audiooutput: HDA Intel PCH, HDMI 3-Hardware device with all software conversions
12.0 audiooutput: HDA Intel PCH, HDMI 4-Hardware device with all software conversions
13.0 audiooutput: UA-25EX, USB Audio-Hardware device with all software conversions

In both cases the USB interface is active.

gogins commented 4 years ago

https://alsa.opensrc.org/Edirol_UA-25EX#a2.0 https://stackoverflow.com/questions/47137683/chromium-alsa-ouput-device-flag-not-working

gogins commented 4 years ago

I got WebAudio audio input from the browser to work by passing a buffer size of 0 to csoundSetHostImplementedAudio, and using Csound's input channel count not the host's input buffer channel count to iterate over the input audio buffer and spin buffer, and calling Csound.PerformKsmps after reading into spin but before writing out from spout.

gogins commented 4 years ago

My Tascam DR-40 can be used as a stereo condenser mic if I go into pre-record (flashing red), turn up the playback volume, and plug the headphone output into my USB audio inputs.

gogins commented 4 years ago

Built the newlook branch of CsoundQt with html5 support using the web engine. All logging from Csound in HTML goes to the CsoundQt message console, not to the registered Csound callback.

minimal.html works (with WebAudio). player.html works. message.html fails with: [C][file:///home/mkg/csound-extended/WebAssembly/examples/message.html.html:312 unknown] Uncaught TypeError: csound.SetControlChannel is not a function.

The camel case of most CsoundQt JavaScript API function names conflicts with my code.

gogins commented 4 years ago

I will enter a few issues in the CsoundQt repo to fix some of the HTML5 issues, but I will not do the work.

gogins commented 4 years ago

Getting -inf samples in csound.node with duplex.html, scrims.html works fine.

gogins commented 4 years ago

Audio configuration for Ubuntu is not well documented, especially not for musicians or programmers. However, I have learned some things.

It is indeed possible to permanently turn off PulseAudio and use only plain ALSA for all audio interfacing. This provides audio with less overhead and fewer glitches, but only for one application at a time. This is the best choice for me and probably for most serious musicians.

The basic thing in ALSA is a "card," and their names should be determined thus:

mkg@xenakis:~/csound-extended/WebAssembly/examples$ cat /proc/asound/cards
 0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xdf240000 irq 138
 1 [UA25EX         ]: USB-Audio - UA-25EX
                      EDIROL UA-25EX at usb-0000:00:14.0-4, full speed

Cards in turn have devices, which can be discovered thus ([card number - device number]):

mkg@xenakis:~/csound-extended/WebAssembly/examples$ cat /proc/asound/devices
  1:        : sequencer
  2: [ 1]   : control
  3: [ 1- 0]: digital audio playback
  4: [ 1- 0]: digital audio capture
  5: [ 1- 0]: raw midi
  6: [ 0]   : control
  7: [ 0- 3]: digital audio playback
  8: [ 0- 7]: digital audio playback
  9: [ 0- 8]: digital audio playback
 10: [ 0- 9]: digital audio playback
 11: [ 0-10]: digital audio playback
 12: [ 0- 2]: hardware dependent
 33:        : timer

More information can be obtained thus, which lists all available cards and their devices:

mkg@xenakis:~/csound-extended/WebAssembly/examples$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
pulse
    PulseAudio Sound Server
default
hdmi:CARD=PCH,DEV=0
    HDA Intel PCH, HDMI 0
    HDMI Audio Output
... und so weiter.

The difference between hw and plughw is important; hw identifies a device that can use only its native sample rate and format, plughw identifies the same device, but with the addition of a plugin that automatically handles sample rate and format conversions. For our purposes plughw should always be used. The audio format conversions in ALSA behaves as though they are considerably more efficient than those in PulseAudio.

For the pieces in this issue, the Csound options should usually be:

-d -f -m195 -+rtaudio=alsa -odac:plughw:1,0 [ -iadc:plughw:1,0 ]

In the browser, there is only 1 input channel, outside the browser there are 2 input channels.

It is vital to understand that with plain ALSA, only one audio stream can be active at a time. Hence, in the browser, only one tab can use audio at a time. Other audio tabs should be closed before running a WebAssembly piece.

The Chromium browser is invoked by the shell script /usr/bin/chromium-browser. Normally Chromium uses PulseAudio. This script implies that the browser audio configuration can be overridden to use plain ALAS in an initialization file or in an environment variable, but I could not get that to work. However, adding these flags to the final invocation of the command in the startup script does work (although this will break Chromium for anybody who uses PulseAudio or a different ALSA device):

else
  if [ $want_temp_profile -eq 0 ] ; then
    # MKG changed 2020-04-14: exec $LIBDIR/$APPNAME $CHROMIUM_FLAGS "$@"
    exec $LIBDIR/$APPNAME $CHROMIUM_FLAGS --alsa-input-device='plughw:1,0' --alsa-output-device='plughw:1,0' "$@"
  else
    # we can't exec here as we need to clean-up the temporary profile
    $LIBDIR/$APPNAME $CHROMIUM_FLAGS "$@"
    rm -rf $TEMP_PROFILE
  fi
fi
gogins commented 4 years ago

Got message.html to play in Android. There are some things I need to change.

gogins commented 4 years ago

The problem on Android and in CsoundQt is that not all the Csound class API methods exposed in JavaScript have initial caps. Most are in camel case. Options:

It's not clear to me if SWIG will automatically wrap less derived functions in simple inheritance. But I have multiple inheritance, anyway.

gogins commented 4 years ago

I have added initial caps signatures to all CsoundOboe methods exposed to JavaScript.

gogins commented 4 years ago
gogins commented 4 years ago

This is now working well enough for government work.