sinneb / pyfluidsynth

Automatically exported from code.google.com/p/pyfluidsynth
1 stars 0 forks source link

Cannot change bit depth from 8 bits #2

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago

So far, I can't sort out how to change the sampling bit depth.
Currently it produces just 8bit, so that the sound quality is 
very poor.  I would like 32.  (I'm still looking...)

M

Original issue reported on code.google.com by mondif...@gmail.com on 26 Jun 2011 at 4:58

GoogleCodeExporter commented 9 years ago

That is, the samples in the variable "s" when I run "test2.py" in the ./test 
dir only assumes about 256 values, even though I can see that the code is 
calling fluid_synth_write_s16, which should produce signed 16-bit integers.  
Any ideas?

M

Original comment by mondif...@gmail.com on 26 Jun 2011 at 6:20

GoogleCodeExporter commented 9 years ago

Dear pyfluidsynth users,

Here's a formal write-up of the issue, and a work-around.

1. What steps will reproduce the problem?

running example code test2.py

2. What is the expected output? What do you see instead?

simply note that the output stored in the array "s" is 8-bit 
(has just ~256 levels) rather than 16-bit.  As a result, the 
sound quality is horrible.  The latter (16 bit) is expected 
since the function fluid_synth_write_s16() is being called
by pyfluidsynth.

3. What version of the product are you using? On what operating system?

version 1.2.4 on Debian Squeeze (6.0.1a)

4. Please provide any additional information below.

The problem seems to be with Fluidsynth itself.  For some reason, the 
function fluid_synth_write_s16 was generating 8 bit values rather than
16 bit values.  For my purposes, it was fine to change fluidsynth.py
by replacing all calls to fluid_synth_write_s16() with calls to 
fluid_synth_write_float(), taking care to change the data types and
buffer size appropriately.  Here is a patch (generated by diffing the two
files):

153c153
< fluid_synth_write_float = cfunc('fluid_synth_write_float', c_void_p,
---
> fluid_synth_write_s16 = cfunc('fluid_synth_write_s16', c_void_p,
165c165
< def fluid_synth_write_float_stereo(synth, len):
---
> def fluid_synth_write_s16_stereo(synth, len):
172,174c172,174
<     buf = create_string_buffer(len * 8)
<     fluid_synth_write_float(synth, len, buf, 0, 2, buf, 1, 2)
<     return numpy.fromstring(buf[:], dtype=numpy.float32)
---
>     buf = create_string_buffer(len * 4)
>     fluid_synth_write_s16(synth, len, buf, 0, 2, buf, 1, 2)
>     return numpy.fromstring(buf[:], dtype=numpy.int16)
298c298
<         return fluid_synth_write_float_stereo(self.synth, len)
---
>         return fluid_synth_write_s16_stereo(self.synth, len)

To the developers: THANK YOU!

M

Original comment by mondif...@gmail.com on 26 Jun 2011 at 8:23

GoogleCodeExporter commented 9 years ago

Finally, please note that the values output to get_samples will be 
stereo-interleaved
if you apply this patch.  So, for mono just subsample by taking every other 
sample
in the array.

For example:

s     = fl.get_samples(44100 * 2)
inds  = np.arange(0,len(s),2)
s_new = s[inds]

Original comment by mondif...@gmail.com on 26 Jun 2011 at 8:30