audio-playback 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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