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

Outputs 32-bit float instead of signed 16-bit int #10

Open
brandonkirsch opened this issue Feb 26, 2015 · 2 comments
Open

Outputs 32-bit float instead of signed 16-bit int #10

brandonkirsch opened this issue Feb 26, 2015 · 2 comments

Comments

@brandonkirsch
Copy link

This library uses libvorbis which only returns PCM data as 32-bit floats.

This unusual output format is unusable with several other utilities such as node-lame.

I think this library needs a routine similar to vorbisfile.c "ov_read_filter" that uses vorbis_ftoi() to correctly convert 32-bit floating points to the usual & expected signed 16-bit integers.

@mathom
Copy link

mathom commented Jan 21, 2016

You can get by with something (probably slow, but fast enough for my uses) like this:

function float_to_int(options) {
    stream.Transform.call(this, options);
}
util.inherits(float_to_int, stream.Transform);

float_to_int.prototype._transform = function (chunk, enc, cb) {
    var b = new buffer.Buffer(chunk.length/4 * 2);
    for (var i=0, j=0; i<chunk.length; i+=4,j+=2) {
        var f = chunk.readFloatLE(i);
        f = f * 32768;
        if (f > 32767) f = 32767;
        if (f < -32768) f = -32768;

        b.writeInt16LE(Math.floor(f), j);
    }
    this.push(b);
    cb();
};

... SNIP ...

vorbisBuffer.pipe(new float_to_int()).pipe(audioSink);

@jobbautista9
Copy link

You could I think also use the tremor library made by Xiph.org for slower devices incapable of floating-point math (like older ARMs). It uses 16-bit signed samples:

long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){
  int i,j;

  ogg_int32_t **pcm;
  long samples;

  if(vf->ready_state<OPENED)return(OV_EINVAL);

  while(1){
    if(vf->ready_state==INITSET){
      samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
      if(samples)break;
    }

    /* suck in another packet */
    {
      int ret=_fetch_and_process_packet(vf,NULL,1,1);
      if(ret==OV_EOF)
        return(0);
      if(ret<=0)
        return(ret);
    }

  }

  if(samples>0){

    /* yay! proceed to pack data into the byte buffer */

    long channels=ov_info(vf,-1)->channels;

    if(samples>(bytes_req/(2*channels)))
      samples=bytes_req/(2*channels);

    for(i=0;i<channels;i++) { /* It's faster in this order */
      ogg_int32_t *src=pcm[i];
      short *dest=((short *)buffer)+i;
      for(j=0;j<samples;j++) {
        *dest=CLIP_TO_15(src[j]>>9);
        dest+=channels;
      }
    }

    vorbis_synthesis_read(&vf->vd,samples);
    vf->pcm_offset+=samples;
    if(bitstream)*bitstream=vf->current_link;
    return(samples*2*channels);
  }else{
    return(samples);
  }
}

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

No branches or pull requests

3 participants