Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
18 of 19 tasks
gogins opened this issue Apr 9, 2020 · 16 comments
Closed
18 of 19 tasks
Assignees

Comments

@gogins
Copy link
Owner

gogins commented Apr 9, 2020

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)

  • simple.html
  • player.html
  • message.html
  • scrims.html works, but can't be restarted. Good enough for now.
  • cmask.html
  • duplex.html audio works, but I don't like the modulation, I think my DSP logic is faulty. Anyway, the audio input works.

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

  • simple.html works (using WebAudio, of course)
  • player.html works, can't be restarted.
  • message.html works, can't be restarted
  • scrims.html works, can't be restarted.
  • cmask.html error:
cmask.js:95 Uncaught ReferenceError: __dirname is not defined
    at cmask.js:95
    at cmask.html:17
2cmask.html:61 Uncaught TypeError: onPlayClick is not a function
    at HTMLInputElement.onclick (cmask.html:61)
  • duplex.html works, can't be restarted.

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

  • player.html
  • message.html
  • scrims.html
  • duplex.html

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.

  • player.html
  • message.html very glitchy at first, then started to work after minor changes to code.
  • scrims.html needs better logic or better loader.
@gogins gogins self-assigned this Apr 9, 2020
@gogins
Copy link
Owner Author

gogins commented Apr 9, 2020

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

@gogins
Copy link
Owner Author

gogins commented Apr 10, 2020

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
Copy link
Owner Author

gogins commented Apr 11, 2020

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
Copy link
Owner Author

gogins commented Apr 11, 2020

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 added a commit that referenced this issue Apr 11, 2020
@gogins
Copy link
Owner Author

gogins commented Apr 11, 2020

@gogins
Copy link
Owner Author

gogins commented Apr 12, 2020

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
Copy link
Owner Author

gogins commented Apr 12, 2020

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
Copy link
Owner Author

gogins commented Apr 13, 2020

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
Copy link
Owner Author

gogins commented Apr 13, 2020

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
Copy link
Owner Author

gogins commented Apr 13, 2020

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

@gogins
Copy link
Owner Author

gogins commented Apr 14, 2020

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
Copy link
Owner Author

gogins commented Apr 14, 2020

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

  • The get_csound function should not print any messages.
  • The loader script absolutely must avoid loading anything or requiring anything if the csound object already exists (i.e., on Android).
  • I think the Csound scripts should never be loaded in the head but always in the body of the page.

gogins added a commit that referenced this issue Apr 14, 2020
@gogins
Copy link
Owner Author

gogins commented Apr 14, 2020

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:

  • Add delegate methods in CsoundOboe for initial caps. I have created an issue for this in csound-android.
  • Monkey-patch the Csound prototype in csound_loader.js to supply initial caps versions of the camel case method names that I need. After starting out to do this I could see that it is indeed possible, but involves complexities that might turn out to be fragile in the future. So I will not do this.

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

@gogins
Copy link
Owner Author

gogins commented Apr 16, 2020

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

@gogins
Copy link
Owner Author

gogins commented Apr 16, 2020

  • There is a problem in scrims.html on Android. The scope of the Csound object is tricky. That's fixed.
  • On Android with csound_loader.js the message callback is not being called. But this capability was never implemented, stdout was simply redirected.

gogins added a commit that referenced this issue Apr 16, 2020
@gogins
Copy link
Owner Author

gogins commented Apr 17, 2020

This is now working well enough for government work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant