audio-playback 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ $:.unshift(File.join("..", "lib"))
2
+
3
+ require "minitest/autorun"
4
+ require "mocha/test_unit"
5
+ require "shoulda-context"
6
+ require "audio-playback"
7
+
8
+ class MockOutput
9
+
10
+ attr_reader :num_channels
11
+
12
+ def initialize(id, options = {})
13
+ @id = id
14
+ @num_channels = options[:num_channels] || 2
15
+ end
16
+
17
+ def latency
18
+ 1
19
+ end
20
+
21
+ end
22
+
23
+ class MockStream
24
+
25
+ def initialize(output)
26
+ @output = output
27
+ end
28
+
29
+ end
30
+
31
+ module TestHelper
32
+
33
+ DEFAULT_OUTPUT_ID = 0
34
+ OUTPUT_INFO = [
35
+ {
36
+ :defaultHighOutputLatency => 2.3,
37
+ :maxOutputChannels => 1,
38
+ :name => "Test Output 1"
39
+ },
40
+ {
41
+ :defaultHighOutputLatency => 3.2,
42
+ :maxOutputChannels => 2,
43
+ :name => "Test Output 2"
44
+ }
45
+ ]
46
+
47
+ def self.stub_portaudio
48
+ FFI::PortAudio::API.stubs(:Pa_GetDeviceCount).returns(2)
49
+ FFI::PortAudio::API.expects(:Pa_GetDeviceInfo).with(0).at_least_once.returns(TestHelper::OUTPUT_INFO[0])
50
+ FFI::PortAudio::API.expects(:Pa_GetDeviceInfo).with(1).at_least_once.returns(TestHelper::OUTPUT_INFO[1])
51
+ FFI::PortAudio::API.stubs(:Pa_GetDefaultOutputDevice).returns(TestHelper::DEFAULT_OUTPUT_ID)
52
+ FFI::PortAudio::API.stubs(:Pa_Initialize).returns(true)
53
+ FFI::PortAudio::API.stubs(:Pa_Terminate).returns(true)
54
+ AudioPlayback::Device::Stream.any_instance.stubs(:close).returns(true)
55
+ end
56
+
57
+ end
58
+
59
+ TestHelper.stub_portaudio
@@ -0,0 +1,115 @@
1
+ require "helper"
2
+
3
+ class AudioPlayback::Playback::FrameSetTest < Minitest::Test
4
+
5
+ context "FrameSet" do
6
+
7
+ context "#ensure_structure" do
8
+
9
+ context "sound has same number of channels as output" do
10
+
11
+ context "mono file, mono output" do
12
+
13
+ setup do
14
+ @path = "test/media/1-mono-44100.wav"
15
+ @file = AudioPlayback::File.new(@path)
16
+ @sound = AudioPlayback::Sound.new(@file)
17
+ @output = MockOutput.new(1, :num_channels => 1)
18
+ @playback = AudioPlayback::Playback.new(@sound, @output, :stream => MockStream.new(@output))
19
+ @data = @sound.data
20
+ @frames = AudioPlayback::Playback::FrameSet.new(@playback).slice(AudioPlayback::Playback::METADATA.size..-1)
21
+ end
22
+
23
+ should "have two channels of valid data" do
24
+ refute_nil @frames
25
+ assert @frames.kind_of?(Array)
26
+ refute_empty @frames
27
+ assert @frames.all? { |frame_channels| frame_channels.count == @output.num_channels }
28
+ assert @frames.all? { |frame_channels| frame_channels.count == @sound.num_channels }
29
+ assert @frames.all? { |frame_channels| frame_channels.all? { |frame| frame.kind_of?(Float) } }
30
+ end
31
+
32
+ end
33
+
34
+ context "stereo file, stereo output" do
35
+
36
+ setup do
37
+ @path = "test/media/1-stereo-44100.wav"
38
+ @file = AudioPlayback::File.new(@path)
39
+ @sound = AudioPlayback::Sound.new(@file)
40
+ @output = MockOutput.new(1, :num_channels => 2)
41
+ @playback = AudioPlayback::Playback.new(@sound, @output, :stream => MockStream.new(@output))
42
+ @data = @sound.data
43
+ @frames = AudioPlayback::Playback::FrameSet.new(@playback).slice(AudioPlayback::Playback::METADATA.size..-1)
44
+ end
45
+
46
+ should "have one channel of valid data" do
47
+ refute_nil @frames
48
+ assert @frames.kind_of?(Array)
49
+ refute_empty @frames
50
+ assert @frames.all? { |frame_channels| frame_channels.kind_of?(AudioPlayback::Playback::Frame) }
51
+ assert @frames.all? { |frame_channels| frame_channels.count == @output.num_channels }
52
+ assert @frames.all? { |frame_channels| frame_channels.count == @sound.num_channels }
53
+ assert @frames.all? { |frame_channels| frame_channels.all? { |frame| frame.kind_of?(Float) } }
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ context "sound has different number of channels than output" do
61
+
62
+ context "mono file, stereo output" do
63
+
64
+ setup do
65
+ @path = "test/media/1-mono-44100.wav"
66
+ @file = AudioPlayback::File.new(@path)
67
+ @sound = AudioPlayback::Sound.new(@file)
68
+ @output = MockOutput.new(1, :num_channels => 2)
69
+ @playback = AudioPlayback::Playback.new(@sound, @output, :stream => MockStream.new(@output))
70
+ @data = @sound.data
71
+ @frames = AudioPlayback::Playback::FrameSet.new(@playback).slice(AudioPlayback::Playback::METADATA.size..-1)
72
+ end
73
+
74
+ should "have two channels of valid data" do
75
+ refute_nil @frames
76
+ assert @frames.kind_of?(Array)
77
+ refute_empty @frames
78
+ assert @frames.all? { |frame_channels| frame_channels.count == @output.num_channels }
79
+ refute @frames.any? { |frame_channels| frame_channels.count == @sound.num_channels }
80
+ assert @frames.all? { |frame_channels| frame_channels.all? { |frame| frame.kind_of?(Float) } }
81
+ end
82
+
83
+ end
84
+
85
+ context "stereo file, mono output" do
86
+
87
+ setup do
88
+ @path = "test/media/1-stereo-44100.wav"
89
+ @file = AudioPlayback::File.new(@path)
90
+ @sound = AudioPlayback::Sound.new(@file)
91
+ @output = MockOutput.new(1, :num_channels => 1)
92
+ @playback = AudioPlayback::Playback.new(@sound, @output, :stream => MockStream.new(@output))
93
+ @data = @sound.data
94
+ @frames = AudioPlayback::Playback::FrameSet.new(@playback).slice(AudioPlayback::Playback::METADATA.size..-1)
95
+ end
96
+
97
+ should "have one channel of valid data" do
98
+ refute_nil @frames
99
+ assert @frames.kind_of?(Array)
100
+ refute_empty @frames
101
+ assert @frames.all? { |frame_channels| frame_channels.kind_of?(AudioPlayback::Playback::Frame) }
102
+ assert @frames.all? { |frame_channels| frame_channels.count == @output.num_channels }
103
+ refute @frames.any? { |frame_channels| frame_channels.count == @sound.num_channels }
104
+ assert @frames.all? { |frame_channels| frame_channels.all? { |frame| frame.kind_of?(Float) } }
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,46 @@
1
+ require "helper"
2
+
3
+ class AudioPlayback::Playback::FrameTest < Minitest::Test
4
+
5
+ context "Frame" do
6
+
7
+ setup do
8
+ @frame = AudioPlayback::Playback::Frame.new([1, 2, 4])
9
+ assert_equal 3, @frame.size
10
+ end
11
+
12
+ context "#truncate" do
13
+
14
+ should "truncate the frame to the given size" do
15
+ @frame.truncate(1)
16
+ assert_equal 1, @frame.size
17
+ end
18
+
19
+ end
20
+
21
+ context "#fill" do
22
+
23
+ context "with :num_channels option" do
24
+
25
+ should "add n elements to the frame" do
26
+ @frame.fill(3, :num_channels => 3, :channels => [1,2,3])
27
+ assert_equal 4, @frame.size
28
+ assert_equal 0, @frame[0]
29
+ end
30
+
31
+ end
32
+
33
+ context "with no options" do
34
+
35
+ should "add n elements to the frame" do
36
+ @frame.fill(4)
37
+ assert_equal 7, @frame.size
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,27 @@
1
+ require "helper"
2
+
3
+ class AudioPlayback::Playback::StreamDataTest < Minitest::Test
4
+
5
+ context "StreamData" do
6
+
7
+ context "#to_pointer" do
8
+
9
+ setup do
10
+ @path = "test/media/1-mono-44100.wav"
11
+ @file = AudioPlayback::File.new(@path)
12
+ @sound = AudioPlayback::Sound.new(@file)
13
+ @output = MockOutput.new(1, :num_channels => 1)
14
+ @playback = AudioPlayback::Playback.new(@sound, @output, :stream => MockStream.new(@output))
15
+ @data = @playback.data
16
+ end
17
+
18
+ should "return a pointer" do
19
+ refute_nil @data
20
+ assert_kind_of FFI::Pointer, @data
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,111 @@
1
+ require "helper"
2
+
3
+ class AudioPlayback::PlaybackTest < Minitest::Test
4
+
5
+ context "Playback" do
6
+
7
+ setup do
8
+ @path = "test/media/1-mono-44100.wav"
9
+ @sound = AudioPlayback::Sound.load(@path)
10
+ @output = AudioPlayback::Device::Output.by_id(0)
11
+ end
12
+
13
+ context ".play" do
14
+
15
+ setup do
16
+ AudioPlayback::Device::Stream.any_instance.expects(:start).once.returns(true)
17
+ end
18
+
19
+ teardown do
20
+ AudioPlayback::Device::Stream.any_instance.unstub(:start)
21
+ end
22
+
23
+ should "start playback" do
24
+ @playback = AudioPlayback::Playback.play(@sound, @output)
25
+ refute_nil @playback
26
+ assert_kind_of AudioPlayback::Playback::Action, @playback
27
+ end
28
+
29
+ end
30
+
31
+ context "#start" do
32
+
33
+ setup do
34
+ @playback = AudioPlayback::Playback.new(@sound, @output)
35
+ AudioPlayback::Device::Stream.any_instance.expects(:start).once.returns(true)
36
+ end
37
+
38
+ teardown do
39
+ AudioPlayback::Device::Stream.any_instance.unstub(:start)
40
+ end
41
+
42
+ should "start playback" do
43
+ @result = @playback.start
44
+ assert_kind_of AudioPlayback::Playback::Action, @result
45
+ end
46
+
47
+ end
48
+
49
+ context "#block" do
50
+
51
+ setup do
52
+ @playback = AudioPlayback::Playback.new(@sound, @output)
53
+ AudioPlayback::Device::Stream.any_instance.expects(:block).once.returns(true)
54
+ end
55
+
56
+ teardown do
57
+ AudioPlayback::Device::Stream.any_instance.unstub(:block)
58
+ end
59
+
60
+ should "defer to stream" do
61
+ assert @playback.block
62
+ end
63
+
64
+ end
65
+
66
+ context "#report" do
67
+
68
+ setup do
69
+ @logger = Object.new
70
+ @playback = AudioPlayback::Playback.new(@sound, @output)
71
+ @logger.expects(:puts).at_least_once
72
+ end
73
+
74
+ teardown do
75
+ @logger.unstub(:puts)
76
+ end
77
+
78
+ should "do logging" do
79
+ assert @playback.report(@logger)
80
+ end
81
+
82
+ end
83
+
84
+ context "#data_size" do
85
+
86
+ setup do
87
+ @playback = AudioPlayback::Playback.new(@sound, @output)
88
+ @size = @playback.data_size
89
+ @metadata_size = AudioPlayback::Playback::METADATA.count * AudioPlayback::Playback::FRAME_SIZE.size
90
+ @sound_data_size = (@sound.size * @sound.num_channels) * AudioPlayback::Playback::FRAME_SIZE.size
91
+ @total_size = @metadata_size + @sound_data_size
92
+ end
93
+
94
+ should "have data size" do
95
+ refute_nil @size
96
+ assert @size > 0
97
+ end
98
+
99
+ should "be larger than sound file data size" do
100
+ assert @size > @sound_data_size
101
+ end
102
+
103
+ should "be equal to sound file plus metadata size" do
104
+ assert_equal @total_size, @size
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,80 @@
1
+ require "helper"
2
+
3
+ class AudioPlayback::SoundTest < Minitest::Test
4
+
5
+ context "Sound" do
6
+
7
+ context "#populate" do
8
+
9
+ context "mono" do
10
+
11
+ setup do
12
+ @path = "test/media/1-mono-44100.wav"
13
+ @file = AudioPlayback::File.new(@path)
14
+ @sound = AudioPlayback::Sound.new(@file)
15
+ @data = @sound.data
16
+ @size = @sound.size
17
+ end
18
+
19
+ should "populate data" do
20
+ refute_nil @data
21
+ refute_nil @size
22
+ assert @data.kind_of?(Array)
23
+ refute_empty @data
24
+ assert_equal @size, @data.size
25
+ refute_empty @data
26
+ assert @data.all? { |frame| frame.kind_of?(Float) }
27
+ assert @data.all? { |frame| frame >= -1 }
28
+ assert @data.all? { |frame| frame <= 1 }
29
+ end
30
+
31
+ end
32
+
33
+ context "stereo" do
34
+
35
+ setup do
36
+ @path = "test/media/1-stereo-44100.wav"
37
+ @file = AudioPlayback::File.new(@path)
38
+ @sound = AudioPlayback::Sound.new(@file)
39
+ @data = @sound.data
40
+ @size = @sound.size
41
+ end
42
+
43
+ should "populate data" do
44
+ refute_nil @data
45
+ refute_nil @size
46
+ assert @data.kind_of?(Array)
47
+ refute_empty @data
48
+ assert_equal @size, @data.size
49
+ assert @data.all? { |frame_channels| frame_channels.kind_of?(Array) }
50
+ assert @data.all? { |frame_channels| frame_channels.all? { |frame| frame.kind_of?(Float) } }
51
+ assert @data.all? { |frame_channels| frame_channels.all? { |frame| frame >= -1 } }
52
+ assert @data.all? { |frame_channels| frame_channels.all? { |frame| frame <= 1 } }
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ context "#report" do
60
+
61
+ setup do
62
+ @logger = Object.new
63
+ @path = "test/media/1-mono-44100.wav"
64
+ @sound = AudioPlayback::Sound.load(@path)
65
+ @logger.expects(:puts).times(4)
66
+ end
67
+
68
+ teardown do
69
+ @logger.unstub(:puts)
70
+ end
71
+
72
+ should "do logging" do
73
+ assert @sound.report(@logger)
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+
80
+ end