A
download pvoc.rb
Language: Ruby
LOC: 243
Project Info
Snd
Server: SourceForge
Type: cvs
SourceForge\s\snd\snd\cvs‑snd\
   _new_snd-test.rb
   _sndlib.h
   aclocal.m4
   analog-filter.scm
   audinfo.c
   audio.c
   autosave.scm
   bess.rb
   bess.scm
   bess1.rb
   bess1.scm
   bird.rb
   bird.scm
   clm-ins.rb
   clm-ins.scm
   clm-strings.h
   clm.c
   clm.h
   clm23.scm
   clm2xen.c
   clm2xen.h
   cmn-glyphs.lisp
   config.guess
   config.h.in
   config.rpath
   config.sub
   configure.ac
   debug.scm
   dlocsig.rb
   draw.rb
   draw.scm
   dsp.rb
   dsp.scm
   edit-menu.scm
   edit123.scm
   effects-utils.scm
   effects.rb
   env.rb
   env.scm
   enved.scm
   eval-c.scm
   event.scm
   examp.rb
   examp.scm
   extensions.rb
   extensions.scm
   fade.scm
   fft-menu.scm
   fix-optargs.scm
   fmv.scm
   freeverb.rb
   freeverb.scm
   gettext.h
   gl.c
   grani.scm
   gtk-effects.scm
   gtk-popup.scm
   gui.scm
   headers.c
   help-snd-fm.pd
   help-snd.pd
   HISTORY.Snd
   hooks.rb
   hooks.scm
   index.rb
   index.scm
   inf-snd.el
   io.c
   jcrev.scm
   ladspa-help.scm
   ladspa.scm
   makefile.in
   makefile.no-gettext
   maraca.rb
   maraca.scm
   marks-menu.scm
   marks.rb
   marks.scm
   maxf.rb
   maxf.scm
   midi.c
   misc.scm
   mix-menu.scm
   mix.rb
   mix.scm
   mixer.scm
   moog.scm
   musglyphs.rb
   musglyphs.scm
   nb.rb
   nb.scm
   new-backgrounds.scm
   new-buttons.scm
   new-effects.scm
   new-icons.scm
   noise.rb
   noise.scm
   old-mac-audio.c
   old-snd.spec
   oo.scm
   oscope.scm
   panic.scm
   pd-add.scm
   pd-any.scm
   pd-fm.scm
   pd-global.scm
   pd-inout.scm
   pd-local.scm
   pd-mozilla.scm
   pd-send_receive.scm
   peak-env.scm
   piano.rb
   piano.scm
   play.rb
   play.scm
   poly.rb
   poly.scm
   popup.rb
   popup.scm
   prc95.rb
   prc95.scm
   pvoc.rb
   pvoc.scm
   README.Snd
   rgb.rb
   rgb.scm
   rmsgain.scm
   rt-compiler.scm
   rt-engine.scm
   rt-examples.scm
   rt.tex
   rtio.rb
   rtio.scm
   rubber.rb
   rubber.scm
   saw.c
   singer.rb
   singer.scm
   snd-0.h
   snd-1.h
   snd-axis.c
   snd-chn.c
   snd-completion.c
   snd-dac.c
   snd-data.c
   snd-draw.c
   snd-edits.c
   snd-env.c
   snd-error.c
   snd-fft.c
   snd-file.c
   snd-file.h
   snd-find.c
   snd-g0.h
   snd-g1.h
   snd-gchn.c
   snd-gdraw.c
   snd-gdrop.c
   snd-genv.c
   snd-gfft.c
   snd-gfile.c
   snd-gfind.c
   snd-ghelp.c
   snd-gl.scm
   snd-glistener.c
   snd-gmain.c
   snd-gmenu.c
   snd-gmix.c
   snd-gprefs.c
   snd-gprint.c
   snd-grec.c
   snd-gregion.c
   snd-gsnd.c
   snd-gtk.scm
   snd-gutils.c
   snd-gxbitmaps.c
   snd-gxcolormaps.c
   snd-gxen.c
   snd-gxutils.c
   snd-help.c
   snd-hobbit.scm
   snd-io.c
   snd-kbd.c
   snd-ladspa.c
   snd-listener.c
   snd-main.c
   snd-marks.c
   snd-menu.c
   snd-menu.h
   snd-mix.c
   snd-motif.scm
   snd-nogui.c
   snd-nogui0.h
   snd-nogui1.h
   snd-prefs.c
   snd-print.c
   snd-rec.c
   snd-rec.h
   snd-region.c
   snd-run.c
   snd-select.c
   snd-sig.c
   snd-snd.c
   snd-strings.h
   snd-trans.c
   snd-utils.c
   snd-x0.h
   snd-x1.h
   snd-xchn.c
   snd-xdraw.c
   snd-xdrop.c
   snd-xen.c
   snd-xenv.c
   snd-xfft.c
   snd-xfile.c
   snd-xfind.c
   snd-xhelp.c
   snd-xlistener.c
   snd-xm.rb
   snd-xmain.c
   snd-xmenu.c
   snd-xmix.c
   snd-xprefs.c
   snd-xprint.c
   snd-xrec.c
   snd-xref.c
   snd-xregion.c
   snd-xsnd.c
   snd-xutils.c
   snd-xxen.c
   snd.1
   Snd.ad
   snd.c
   Snd.gtkrc
   snd.h
   snd.spec
   snd_conffile.scm
   snd_pd_external.c
   snd_pd_external.h
   snd4.scm
   snd5.scm
   snd6.scm
   snd7.scm
   sndctrl.c
   sndinfo.c
   sndlib-strings.h
   sndlib.h.in
   sndlib2xen.c
   sndlib2xen.h
   sndplay.c
   sndrecord.c
   sndwarp.scm
   sound.c
   special-menu.scm
   spectr.rb
   spectr.scm
   strad.rb
   strad.scm
   TODO.Snd
   track-colors.scm
   v.rb
   v.scm
   vct.c
   vct.h
   ws.rb
   ws.scm
   xen.c
   xen.h
   xg-x11.h
   xm-enved.rb
   xm-enved.scm
   zip.rb
   zip.scm

# pvoc.rb -- pvoc.scm -> pvoc.rb -*- snd-ruby -*-

# Translator: Michael Scholz <scholz-micha@gmx.de>
# Created: Sat Mar 27 00:19:51 CET 2004
# Last: Tue Mar 15 00:45:35 CET 2005

# Comment:
# 
# versions of the Moore-Klingbeil-Trevisani-Edwards phase-vocoder
#
# class Pvocoder
#   initialize(fftsize, overlap, interp, analyze, edit, synthesize)
#   inspect
#   pvocoder(input)
#
#  make_pvocoder(fftsize, overlap, interp, analyze, edit, synthesize)
#  pvocoder(pv, input)
#
#  test_pv_1
#  test_pv_2(freq)
#  test_pv_3(time)
#  test_pv_4(gate)
#  
#  pvoc(*rest)
#  
# Code:

require "examp"
require "ws"

class Pvocoder
  def initialize(fftsize, overlap, interp, analyze, edit, synthesize)
    @output     = interp
    @interp     = interp
    @hop        = overlap
    @filptr     = 0
    @N          = fftsize
    @window     = vct_scale!(make_fft_window(Hamming_window, fftsize), 2.0 / (0.54 * fftsize))
    @D          = fftsize / overlap
    @in_data    = nil
    @ampinc     = make_vct(fftsize)
    @freqs      = make_vct(fftsize)
    @amps       = make_vct(fftsize / 2)
    @phaseinc   = make_vct(fftsize / 2)
    @phases     = make_vct(fftsize / 2)
    @lastphase  = make_vct(fftsize / 2)
    @analyze    = analyze
    @edit       = edit
    @synthesize = synthesize
  end

  def inspect
    format("#<%s outctr: %d, interp: %d, filptr: %d, N: %d, D: %d, in_data: %s>",
           self.class, @output, @interp, @filptr, @N, @D, @in_data.inspect)
  end
  
  def pvocoder(input)
    if @output >= @interp
      if @analyze
        @analyze.call(self, input)
      else
        vct_fill!(@freqs, 0.0)
        @output = 0
        if (not vct?(@in_data))
          @in_data = make_vct!(@N) do input.call end
        else
          vct_move!(@in_data, 0, @D)
          ((@N - @D)...@N).each do |i| @in_data[i] = input.call end
        end
        buf = @filptr % @N
        if buf.zero?
          vct_fill!(@ampinc, 0.0)
          vct_add!(@ampinc, @in_data)
          vct_multiply!(@ampinc, @window)
        else
          @N.times do |k|
            @ampinc[buf] = @window[k] * @in_data[k]
            buf += 1
            if buf >= @N
              buf = 0
            end
          end
        end
        @filptr += @D
        mus_fft(@ampinc, @freqs, @N, 1)
        rectangular2polar(@ampinc, @freqs)
      end
      if @edit
        @edit.call(self)
      else
        pscl = 1.0 / @D
        kscl = TWO_PI / @N
        (@N / 2).times do |k|
          phasediff = @freqs[k] - @lastphase[k]
          @lastphase[k] = @freqs[k]
          while phasediff > PI
            phasediff -= TWO_PI
          end
          while phasediff < -TWO_PI
            phasediff += TWO_PI
          end
          @freqs[k] = pscl * phasediff + k * kscl
        end
      end
      scl = 1.0 / @interp
      vct_subtract!(@ampinc, @amps)
      vct_subtract!(@freqs, @phaseinc)
      vct_scale!(@ampinc, scl)
      vct_scale!(@freqs, scl)
    end
    @output += 1
    if @synthesize
      @synthesize.call
    else
      vct_add!(@amps, @ampinc)
      vct_add!(@phaseinc, @freqs)
      vct_add!(@phases, @phaseinc)
      sine_bank(@amps, @phases)
    end
  end
end

add_help(:make_pvocoder,
         "make_pvocoder(fftsize, overlap, interp, [analyze=false, [edit=false, [synthesize=false]]])
makes a new (Ruby-based, not CLM) phase-vocoder generator")
def make_pvocoder(fftsize = 512,
                  overlap = 4,
                  interp = 128,
                  analyze = false,
                  edit = false,
                  synthesize = false)
  Pvocoder.new(fftsize, overlap, interp, analyze, edit, synthesize)
end

add_help(:pvocoder,
         "pvocoder(pv, input) is the phase-vocoder generator associated with make_pvocoder")
def pvocoder(pv, input)
  pv.pvocoder(input)
end

=begin
let(open_sound("oboe.snd"),
    make_pvocoder(256, 4, 64),
    make_sample_reader(0)) do |ind, pv, rd|
  map_channel(lambda do |y| pvocoder(pv, rd) end)
  play_and_wait(0, ind)
  save_sound_as("pvoc.snd", ind)
  revert_sound(ind)
  close_sound(ind)
  open_sound("pvoc.snd")
end
=end

def test_pv_1
  pv = make_phase_vocoder(false, 512, 4, 128, 1.0, false, false, false)
  rd = make_sample_reader(0)
  map_channel(lambda do |y| phase_vocoder(pv, lambda do |dir| next_sample(rd) end) end)
  free_sample_reader(rd)
end

def test_pv_2(freq)
  pv = make_phase_vocoder(false, 512, 4, 128, freq, false, false, false)
  rd = make_sample_reader(0)
  map_channel(lambda do |y| phase_vocoder(pv, lambda do |dir| next_sample(rd) end) end)
  free_sample_reader(rd)
end

def test_pv_3(time)
  pv = make_phase_vocoder(false, 512, 4, (time * 128.0).floor, 1.0, false, false, false)
  rd = make_sample_reader(0)
  len = (time * frames).floor
  data = make_vct!(len) do phase_vocoder(pv, lambda do |dir| next_sample(rd) end) end
  free_sample_reader(rd)
  vct2channel(data, 0, len)
end

def test_pv_4(gate)
  pv = make_phase_vocoder(false,
                          512, 4, 128, 1.0,
                          false,
                          lambda { |v|
                            phase_vocoder_amp_increments(v).map! do |val|
                              if val < gate
                                0.0
                              else
                                val
                              end
                              true
                            end
                          }, false)
  rd = make_sample_reader(0)
  map_channel(lambda do |y| phase_vocoder(pv, lambda do |dir| next_sample(rd) end) end)
  free_sample_reader(rd)
end

# another version of the phase vocoder

add_help(:pvoc,
         "(pvoc, *rest) [fftsize, overlap, time, pitch, gate, hoffset, snd, chn] \
applies the phase vocoder algorithm to the current sound (i.e. fft analysis, \
oscil bank resynthesis). 'pitch' specifies the pitch transposition ratio, 'time' - \
specifies the time dilation ratio, 'gate' specifies a resynthesis gate in dB (partials \
with amplitudes lower than the gate value will not be synthesized), \
'hoffset is a pitch offset in Hz.")
def pvoc(*rest) 
  fftsize = get_args(rest, :fftsize, 512)
  overlap = get_args(rest, :overlap, 4)
  time    = get_args(rest, :time, 1.0)
  pitch   = get_args(rest, :pitch, 1.0)
  gate    = get_args(rest, :gate, 0.0)
  hoffset = get_args(rest, :hoffset, 0.0)
  snd     = get_args(rest, :snd, false)
  chn     = get_args(rest, :chn, false)
  len = frames(snd, chn)
  filptr = 0
  sr = srate(snd)
  fftsize2 = fftsize / 2
  d = fftsize / overlap
  interp = d * time
  syngate = gate.zero? ? 0.0 : (10 ** (-gate.abs / 20.0))
  poffset = hz2radians(hoffset)
  window = make_fft_window(Hamming_window, fftsize)
  fdr = make_vct(fftsize)
  fdi = make_vct(fftsize)
  lastphase = make_vct(fftsize2)
  lastamp = make_vct(fftsize2)
  lastfreq = make_vct(fftsize2)
  ampinc = make_vct(fftsize2)
  freqinc = make_vct(fftsize2)
  fundamental = TWO_PI / fftsize
  output = interp
  resynth_oscils = make_array(fftsize2) do make_oscil(:frequency, 0) end
  nextpct = 10.0
  outlen = (time * len).floor
  in_data = channel2vct(0, fftsize * 2, snd, chn)
  in_data_beg = 0
  vct_scale!(window, 2.0 / (0.54 * fftsize))
  out_data = make_vct([len, outlen].max)
  out_data.length.times do |i|
    if output >= interp
      break if c_g?
      output = 0
      buffix = filptr % fftsize
      vct_fill!(lastamp, 0.0)
      vct_fill!(lastfreq, 0.0)
      vct_add!(lastamp, fdr)
      vct_add!(lastfreq, fdi)
      fftsize.times do |k|
        fdr[buffix] = window[k] * in_data[filptr - in_data_beg]
        filptr += 1
        buffix += 1
        if buffix >= fftsize
          buffix = 0
        end
      end
      filptr -= fftsize - d
      if filptr > in_data_beg + fftsize
        in_data_beg = filptr
        in_data = channel2vct(in_data_beg, fftsize * 2, snd, chn)
      end
      vct_fill!(fdi, 0.0)
      mus_fft(fdr, fdi, fftsize, 1)
      fftsize2.times do |k|
        a = fdr[k]
        b = fdi[k]
        mag = sqrt(a * a + b * b)
        phase = 0
        phasediff = 0
        fdr[k] = mag
        if mag > 0
          phase = -atan2(b, a)
          phasediff = phase - lastphase[k]
          lastphase[k] = phase
          while phasediff > PI
            phasediff -= TWO_PI
          end
          while phasediff < -PI
            phasediff += TWO_PI
          end
        end
        fdi[k] = pitch * ((phasediff * sr) / (d * sr) + k * fundamental + poffset)
        if fdr[k] < syngate
          fdr[k] = 0.0
        end
        ampinc[k] = (fdr[k] - lastamp[k]) / interp
        freqinc[k] = (fdi[k] - lastfreq[k]) / interp
      end
    end
    output += 1
    vct_add!(lastamp, ampinc)
    vct_add!(lastfreq, freqinc)
    out_data[i] = oscil_bank(lastamp, resynth_oscils, lastfreq)
  end
  vct2channel(out_data, 0, out_data.length)
end

# pvoc.rb ends here

About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us