Class: ALSA::PCM::Playback

Inherits:
Stream
  • Object
show all
Defined in:
lib/alsa/pcm/playback.rb

Instance Attribute Summary

Attributes inherited from Stream

#buffer_time_size, #handle

Instance Method Summary collapse

Methods inherited from Stream

#available_frame_count, #buffer_frame_count, #change_hardware_parameters, #change_software_parameters, #check_handle!, #close, #hardware_parameters, #hardware_parameters=, #open, open, #opened?, #software_parameters

Instance Method Details

#native_constantObject



4
5
6
# File 'lib/alsa/pcm/playback.rb', line 4

def native_constant
  ALSA::PCM::Native::Stream::PLAYBACK
end

#writeObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/alsa/pcm/playback.rb', line 72

def write
  check_handle!

  ALSA.logger.debug { "start write with #{hw_params.inspect}" }

  FFI::MemoryPointer.new(:char, hw_params.buffer_size_for(buffer_frame_count)) do |buffer|
    while audio_content = yield(buffer.size)
      buffer.write_string audio_content

      read_frame_count = 
        if audio_content.size == buffer.size
          buffer_frame_count 
        else
          hw_params.frame_count_for(audio_content.size)
        end

      write_buffer buffer, read_frame_count
    end
  end
end

#write_buffer(buffer, frame_count) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/alsa/pcm/playback.rb', line 8

def write_buffer(buffer, frame_count)
  check_handle!
  
  write_count = ALSA::try_to "write in audio interface" do
    response = ALSA::PCM::Native::writei(self.handle, buffer, frame_count)
    if ALSA::Native::error_code?(response)
      ALSA.logger.warn { "try to recover '#{ALSA::Native::strerror(response)}' on write"}
      ALSA::PCM::Native::pcm_recover(self.handle, response, 1)
    else
      response
    end
  end

  ALSA.logger.debug { "write frame count: #{write_count}/#{frame_count}"}

  missing_frame_count = frame_count - write_count
  if missing_frame_count > 0
    ALSA.logger.debug { "missing wroted frame count: #{missing_frame_count}"}
  end
end

#write_in_background(&block) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/alsa/pcm/playback.rb', line 29

def write_in_background(&block)
  check_handle!

  async_handler = FFI::MemoryPointer.new(:pointer)
  buffer = FFI::MemoryPointer.new(:char, hw_params.buffer_size_for(buffer_frame_count))

  started = false

  playback_callback = Proc.new do |async_handler|
    if started
      audio_content = yield(buffer.size)
      buffer.write_string audio_content
    
      read_frame_count = 
        if audio_content.size == buffer.size 
          buffer_frame_count
        else
          hw_params.frame_count_for(audio_content.size)
        end
      
      write_buffer buffer, read_frame_count
    end
  end

  ALSA::try_to "add pcm handler" do
    ALSA::Native::async_add_pcm_handler(async_handler, handle, playback_callback, nil)
  end

  ALSA::try_to "start playback" do
    ALSA::PCM::Native::start(handle)
  end

  silent_frame_count = ALSA::try_to "read available space" do
    ALSA::PCM::Native::avail_update(self.handle)
  end
  ALSA.logger.debug { "write synchronously a silence of #{silent_frame_count} frames"}
  FFI::MemoryPointer.new(:char, hw_params.buffer_size_for(silent_frame_count)) do |silent|
    ALSA::PCM::Native::writei self.handle, silent, silent_frame_count
  end

  started = true
end