1+ /*
2+ * Copyright 2025 Alex Andres
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ package dev .onvoid .webrtc .media .audio ;
18+
19+ import static org .junit .jupiter .api .Assertions .*;
20+
21+ import dev .onvoid .webrtc .TestBase ;
22+ import dev .onvoid .webrtc .media .MediaSource ;
23+
24+ import org .junit .jupiter .api .AfterEach ;
25+ import org .junit .jupiter .api .BeforeEach ;
26+ import org .junit .jupiter .api .Test ;
27+
28+ import java .util .concurrent .atomic .AtomicBoolean ;
29+ import java .util .concurrent .atomic .AtomicInteger ;
30+
31+ class CustomAudioSourceTest extends TestBase {
32+
33+ private CustomAudioSource customAudioSource ;
34+
35+
36+ @ BeforeEach
37+ void init () {
38+ customAudioSource = new CustomAudioSource ();
39+ }
40+
41+ @ AfterEach
42+ void dispose () {
43+
44+ }
45+
46+ @ Test
47+ void stateAfterCreation () {
48+ assertEquals (MediaSource .State .LIVE , customAudioSource .getState ());
49+ }
50+
51+ @ Test
52+ void addNullSink () {
53+ assertThrows (NullPointerException .class , () -> {
54+ AudioTrack audioTrack = factory .createAudioTrack ("audioTrack" , customAudioSource );
55+ audioTrack .addSink (null );
56+ audioTrack .dispose ();
57+ });
58+ }
59+
60+ @ Test
61+ void removeNullSink () {
62+ assertThrows (NullPointerException .class , () -> {
63+ AudioTrack audioTrack = factory .createAudioTrack ("audioTrack" , customAudioSource );
64+ audioTrack .removeSink (null );
65+ audioTrack .dispose ();
66+ });
67+ }
68+
69+ @ Test
70+ void addRemoveSink () {
71+ AudioTrack audioTrack = factory .createAudioTrack ("audioTrack" , customAudioSource );
72+ AudioTrackSink sink = (data , bitsPerSample , sampleRate , channels , frames ) -> { };
73+
74+ audioTrack .addSink (sink );
75+ audioTrack .removeSink (sink );
76+ audioTrack .dispose ();
77+ }
78+
79+ @ Test
80+ void pushAudioData () {
81+ // 16-bit, 48kHz, stereo, 10ms
82+ testAudioFormat (16 , 48000 , 2 , 480 );
83+ }
84+
85+ @ Test
86+ void pushAudioWithDifferentFormats () {
87+ testAudioFormat (8 , 8000 , 1 , 80 ); // 8-bit, 8kHz, mono, 10ms
88+ testAudioFormat (16 , 16000 , 1 , 160 ); // 16-bit, 16kHz, mono, 10ms
89+ testAudioFormat (16 , 44100 , 2 , 441 ); // 16-bit, 44.1kHz, stereo, 10ms
90+ testAudioFormat (16 , 48000 , 2 , 480 ); // 16-bit, 48kHz, stereo, 10ms
91+ }
92+
93+ private void testAudioFormat (int bitsPerSample , int sampleRate , int channels , int frameCount ) {
94+ AudioTrack audioTrack = factory .createAudioTrack ("audioTrack" , customAudioSource );
95+
96+ final AtomicBoolean dataReceived = new AtomicBoolean (false );
97+ final AtomicInteger receivedBitsPerSample = new AtomicInteger (0 );
98+ final AtomicInteger receivedSampleRate = new AtomicInteger (0 );
99+ final AtomicInteger receivedChannels = new AtomicInteger (0 );
100+ final AtomicInteger receivedFrames = new AtomicInteger (0 );
101+
102+ AudioTrackSink testSink = (data , bits , rate , chans , frames ) -> {
103+ dataReceived .set (true );
104+ receivedBitsPerSample .set (bits );
105+ receivedSampleRate .set (rate );
106+ receivedChannels .set (chans );
107+ receivedFrames .set (frames );
108+ };
109+
110+ audioTrack .addSink (testSink );
111+
112+ // Create a buffer with test audio data (silence in this case).
113+ int bytesPerSample = bitsPerSample / 8 ;
114+ byte [] audioData = new byte [frameCount * channels * bytesPerSample ];
115+
116+ customAudioSource .pushAudio (audioData , bitsPerSample , sampleRate , channels , frameCount );
117+
118+ // Verify that our sink received the data with correct parameters.
119+ assertTrue (dataReceived .get (), "Audio data was not received by the sink" );
120+ assertEquals (bitsPerSample , receivedBitsPerSample .get (), "Bits per sample doesn't match" );
121+ assertEquals (sampleRate , receivedSampleRate .get (), "Sample rate doesn't match" );
122+ assertEquals (channels , receivedChannels .get (), "Channel count doesn't match" );
123+ assertEquals (frameCount , receivedFrames .get (), "Frame count doesn't match" );
124+
125+ // Clean up.
126+ audioTrack .removeSink (testSink );
127+ audioTrack .dispose ();
128+ }
129+ }
0 commit comments