Re: generating sound with createJavaScriptNode in an emulator

Antonio, which platform are you running on?  I've very recently (as of
yesterday) landed a patch to fix Grant's GameBoy problem on the Mac, but now
we need to get it working on Windows...

On Wed, May 18, 2011 at 1:03 PM, Antonio José Villena Godoy <_@
antoniovillena.es> wrote:

>
>  Hello Chris
>
>  Thank you very much for your reponse.
>
>  1. Yes I did a litte hack rewriting the onaudioprocess function (in my
> computer the buffer doesn't change and works). In a previous version I did
> in the correct way, so fixing it sounds equal (at least in my computer). You
> can ear the bad sound by clicking the last link, and then pressing Enter.
>
>  2. Sorry, I have forgotten the part that fills the "vb" array and init
> variables. This code is when Z80 outs a byte to the port. The only output
> port in ZX Spectrum is 0xFE (a0=0): bits 0..2 are for the border color and
> the important one (bit 4) is connected to the speaker.
>
> function write_port(addr, val) {
>  if( ~addr & 1 ){
>    if( bor^val & 0x10 )
>      vb[vbp]= flash*69888 + st,
>      vbp= vbp+1 & 0xff;
>    document.body.style.backgroundColor=  'rgb('
>                                        + pal[(bor= val)&7].toString()
>                                        + ')';
>  }
> }
>
> init variables:
> sample= playp= vbp= bor= 0;
>
>  I don't want that you read and understand the code, so read only if you
> see it interestant.
>
>  I think that the problem is in the javascript scheduler in Chrome. It
> seems that setInterval is never interrupted by the audio function.
>
>  The emulator basically has only one process (run) called every 20ms. In
> the "run" function, it emulates 69888 cycles of Z80 (3.5MHz), paint the
> screen and generates a Z80 interrupt. Nothing else.
>
>  There is another process, onaudioprocess, launched by createJavaScriptNode
> (not setInterval). In my case it's called every 21.33ms (1024
> samples/48000Hz).
>
>  So I think that actually is very difficult to implement a javascript
> emulator. The other javascript emulator that I knows that implement html5
> sound is the GBC emulator, by Grant Galitz (writes in this mailing list),
> and has the same problem.
>
>  I have this 3 ideas for fixing it:
> 1. Allow pseudothreads (function called by setInterval) to be interrupted
> by onaudioprocess in Chrome.
> 2. Allow to choose custom sample rate.
> 3. Allow to choose any number of samples per buffer (not only a power of
> 2).
>
>  Regards
>
> El 18/05/11 20:47, Chris Rogers escribió:
>
>> Hi Antonio,
>>
>> I can see couple of problems:
>>
>> 1. I notice that you're changing the "onaudioprocess" function, but in
>> the first function you're setting "data".  The audio data buffer will
>> change each and every callback, so you need to set "data" by calling
>> getChannelData(0) again in each call to your buffer function.
>>
>> 2. I don't see where you're initializing the "sample" variable.  Also,
>> it looks like you're doing a bit operation with "sample ^= 0x40".  The
>> sample values should be floating point in a range from -1.0 -> +1.0, not
>> an integer value.
>>
>> 3. Once you have everything else fixed, you'll probably want to increase
>> the buffer size.
>>
>> Cheers,
>> Chris
>>
>> On Wed, May 18, 2011 at 8:47 AM, Antonio José Villena Godoy
>> <_@antoniovillena.es <http://antoniovillena.es>> wrote:
>>
>>
>>      Hello Chris
>>
>>      I am new in this mailing list. My name is Antonio, I am a Spanish
>>    developer. I have created this emulator:
>>
>>    http://jbacteria.antoniovillena.es/
>>
>>      I try to put sound in the emulator with this init code:
>>
>>    if(typeof webkitAudioContext == 'function')
>>      cts= new webkitAudioContext(),
>>      paso= 69888*50/cts.sampleRate,
>>      node= cts.createJavaScriptNode(1024, 0, 1),
>>      node.onaudioprocess= function (e){
>>        data= e.outputBuffer.getChannelData(0);
>>        node.onaudioprocess= buffer;
>>      },
>>      node.connect(cts.destination);
>>
>>      and the buffer function:
>>
>>    function buffer(e) {
>>      play= flash*69888 + st - paso*1024;
>>      j= 0;
>>      while( j<1024 )
>>        if( data[j++]= sample
>>          , (play+= paso) > vb[playp] )
>>          sample^= 0x40,
>>          playp= playp+1 & 0xff;
>>    }
>>
>>      But the quality of the sound is very bad. I have tried to increase
>>    the buffer to 2048 and 4096 with worse result. I don't know if the
>>    problem is mine or a bad Chrome implementation.
>>
>>      As you can see, the 48K sound is very simple, as the PC beeper. I
>>    would like to implement 128K AY-8912 sound, later, if I can fix this
>>    issue.
>>
>>      The source code is here:
>>    http://jbacteria.antoniovillena.es/jBacteriaSourceCode.zip
>>
>>      And a game when you can hear the bad sound is for example:
>>    http://jbacteria.antoniovillena.es/48?fernando
>>
>>      Regards (and sorry for my bad English)
>>    --
>>       ,       _            _       __   ___ _ _
>>      /_\  _ _| |_ ___ _ _ (_)___   \ \ / (_) | |___ _ _  __ _
>>      / _ \| ' \  _/ _ \ ' \| / _ \   \ V /| | | / -_) ' \/ _` |
>>    /_/ \_\_||_\__\___/_||_|_\___/    \_/ |_|_|_\___|_||_\__,_|
>>
>>
>>
>
> --
>   ,       _            _       __   ___ _ _
>  /_\  _ _| |_ ___ _ _ (_)___   \ \ / (_) | |___ _ _  __ _
>  / _ \| ' \  _/ _ \ ' \| / _ \   \ V /| | | / -_) ' \/ _` |
> /_/ \_\_||_\__\___/_||_|_\___/    \_/ |_|_|_\___|_||_\__,_|
>

Received on Wednesday, 18 May 2011 20:11:12 UTC