#!/usr/bin/ruby
# ruby FFI gem rocks! http://rdoc.info/projects/ffi/ffi
# Please note this is experimental code and has awful APIs.
# Learn from it (if you can find anything to learn), but please do not use
# it as-is
require 'rubygems'
require 'ffi'
module PortAudio
extend FFI::Library
ffi_lib 'portaudio'
module Format
Int16=0x8
end
attach_function :Pa_Initialize, [], :int # typedef int PaError
attach_function :Pa_GetVersion, [], :int
attach_function :Pa_GetErrorText, [:int], :string
attach_function :Pa_OpenDefaultStream, [:pointer,:int,:int,:ulong,:double,:ulong,:pointer,:pointer], :int
attach_function :Pa_StartStream, [:pointer], :int
attach_function :Pa_IsStreamActive, [:pointer], :int
attach_function :Pa_WriteStream, [:pointer,:pointer,:ulong], :int
attach_function :Pa_GetStreamWriteAvailable, [:pointer], :long
def self.or_raise
ret=yield
if(ret<0) then
text=Pa_GetErrorText(ret)
raise "PortAudio error #{ret}, #{text}"
end
ret
end
def self.initialize
init=self.Pa_Initialize
if init!=0 then
# how do we test this path?
text=Pa_GetErrorText(init)
raise "Pa_Initialize returned #{init}, #{text}"
end
v=PortAudio.Pa_GetVersion
if v<1899 then
raise "PortAudio version #{v} is too old: need 1899 or newer"
end
end
def self.open_default_stream(n_input_channels,n_output_channels,
format,rate,frames_per_buffer)
@out=FFI::MemoryPointer.new :pointer
puts @out.inspect
Pa_OpenDefaultStream(@out,n_input_channels,n_output_channels,
format,rate,frames_per_buffer,nil,nil)
return @out.get_pointer(0)
end
def self.start_stream(stream)
self.or_raise {
PortAudio.Pa_StartStream(stream)
}
end
def self.stream_write_available(stream)
self.or_raise {
self.Pa_GetStreamWriteAvailable(stream)
}
end
end
buf=nil
file='/big/media/Music/from_usb_stick/Hot Chip/The Warning/Over and Over.mp3'
open("|/usr/local/bin/mplayer -quiet -really-quiet -vc null -vo null -ao pcm:nowaveheader:file=/dev/stdout:fast '#{file}'") { |f|
buf=f.read
}
#buf=buf.slice(0,16000)
puts buf.length
PortAudio.initialize
stream=PortAudio.open_default_stream(0,2,PortAudio::Format::Int16,44100,256);
puts "stream is #{stream}"
puts PortAudio.Pa_IsStreamActive(stream)
PortAudio.start_stream(stream)
puts PortAudio.Pa_IsStreamActive(stream)
off=0
while off<buf.length do
frames=PortAudio.stream_write_available(stream)
puts "off #{off} frames #{frames}"
PortAudio.Pa_WriteStream(stream,buf.slice(off,frames*4),frames)
off+=frames*4
end