1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
 * Audio Module - Audio playback and management system
 * 
 * Features:
 * - Audio playback with WAV files - Support for standard WAV audio format
 * - Audio streaming playback - Real-time audio stream processing
 * - Text-to-speech playback - TTS functionality for text conversion
 * - Volume control and range management - Precise volume control with range validation
 * - Playback interruption and cache management - Advanced playback control and resource management
 * 
 * Usage:
 * - Audio playback service - Background music, sound effects, notifications
 * - TTS service - Voice announcements, accessibility features (not all devices support)
 * - Volume management - System-wide volume control with user-friendly interface
 * - Support cross-thread audio playback
 * - The WAV format should be Channels : 1, Sample Rate : approximately 24000, Precision : 16-bit, other formats need to be converted to this format
 * 
 * Doc/Demo : https://github.com/DejaOS/DejaOS
 */
import { audioClass } from './libvbar-m-dxaudio.so'
 
// Create audio object instance for native operations
const audioObj = new audioClass();
// Export audio module interface
const audio = {}
 
// Playback status code constants
audio.PLAY_CODE = {
    SUCCESS: 0,        // Playback completed successfully
    FAILED: -1,        // Playback operation failed
    QUEUE_IS_FULL: -2  // Playback queue is full, cannot add more audio
}
 
// Language type constants for TTS functionality
audio.PLAY_TYPE = {
    CHINESE_DATA: 0,     /** Chinese language TTS data */
    ENGLISH_DATA: 1,     /** English language TTS data */
}
 
/**
 * Audio system initialization
 * @param {number} [volume=5] Volume level (0-10) - User-friendly volume range (0 means mute), default 5
 * @param {number} [periodSize=512] Period size in samples - Audio processing granularity, default 512
 * @param {number} [bufferSize=2048] Buffer size in samples - Audio buffer capacity, default 2048
 * @throws {Error} If initialization fails - Throws error when audio system cannot be initialized
 * 
 * Technical Details:
 * - periodSize: Controls audio processing latency. Smaller values (256,512) provide lower latency 
 *   but higher CPU usage. Larger values (1024,2048) reduce CPU usage but increase latency.
 * - bufferSize: Determines audio smoothness. Smaller values (1024,2048) use less memory but may 
 *   cause audio stuttering. Larger values (4096,8192) provide smoother playback but use more memory.
 * - Recommended configurations:
 *   * Low latency: (256, 1024) - For real-time communication
 *   * High quality: (1024, 4096) - For music playback
 *   * Balanced: (512, 2048) - For general applications
 */
audio.init = function (volume = 5, periodSize = 512, bufferSize = 2048) {
    // Parameter validation
    validateNumber(volume, 'volume');
    validateNumber(periodSize, 'periodSize');
    validateNumber(bufferSize, 'bufferSize');
 
    // Validate volume range (0-10 for user-friendly interface; 0 means mute)
    if (volume < 0 || volume > 10) {
        throw new Error("audio.init: 'volume' must be between 0 and 10");
    }
 
    // Initialize audio system with specified parameters
    audioObj.audioInit(volume, periodSize, bufferSize)
}
 
/**
 * Audio system deinitialization
 * @returns {boolean} true if deinitialization successful, false otherwise
 * 
 * Note: This function releases all audio resources and should be called
 * when the audio system is no longer needed to prevent resource leaks.
 */
audio.deinit = function () {
    return audioObj.audioDeinit()
}
 
 
/**
 * Get current audio volume level
 * @returns {number} Current volume level (0-10) - Mapped from hardware volume to user-friendly range (0 means mute)
 * 
 * The returned value is automatically mapped from the hardware volume range
 * to the user-friendly 1-10 range for consistent interface experience.
 */
audio.getVolume = function () {
    return audioObj.audioGetVolume()
}
 
/**
 * Set audio volume level
 * @param {number} volume Volume level (0-10), required parameter (0 means mute)
 * @returns {boolean} true if volume set successfully, false otherwise
 * 
 * Volume levels outside the valid range (1-10) will be automatically clamped
 * to the nearest valid value. The function maps user volume to hardware volume
 * internally for optimal audio quality.
 */
audio.setVolume = function (volume) {
    if (volume == undefined || volume == null) {
        throw new Error("audio.setVolume: 'volume' parameter should not be null")
    }
    if (volume < 0 || volume > 10) {
        throw new Error("audio.setVolume: 'volume' must be between 0 and 10")
    }
    return audioObj.audioSetVolume(volume)
}
 
/**
 * Play WAV audio file from file path
 * @param {string} path Absolute path to WAV file, required parameter
 * @returns {number} Playback status code (see audio.PLAY_CODE constants)
 * 
 * File path should start with '/app/code/' and typically placed in the project's
 * resource directory (same level as src directory). Supports standard WAV format.
 * 
 * Return values:
 * - 0: Playback started successfully
 * - -1: Playback failed
 * - -2: Playback queue is full
 */
audio.play = function (path) {
    if (!path) {
        throw new Error("audio.play: 'path' parameter should not be null")
    }
    return audioObj.audioPlayWav(path)
}
 
/**
 * Play audio from ArrayBuffer data (streaming audio)
 * @param {ArrayBuffer} buffer Audio data buffer, required parameter
 * @returns {number} Playback status code (see audio.PLAY_CODE constants)
 * 
 * This function is useful for playing audio streams, real-time audio data,
 * or audio data received from network sources. The buffer should contain
 * valid WAV format audio data.
 */
audio.playWavData = function (buffer) {
    if (!buffer) {
        throw new Error("audio.playWavData: 'buffer' parameter should not be null")
    }
    return audioObj.audioPlayWavData(buffer)
}
 
/**
 * Play text using Text-to-Speech (TTS) functionality
 * @param {string} txt Text to be converted to speech, required parameter
 * @param {number} type Language type, required parameter (0: Chinese, 1: English)
 * @returns {number} Playback status code (see audio.PLAY_CODE constants)
 * 
 * TTS functionality may not be supported on all devices. The function converts
 * the provided text to speech in the specified language and plays it through
 * the audio system.
 * 
 * Language types:
 * - 0: Chinese (中文)
 * - 1: English (English)
 */
audio.playTxt = function (txt, type) {
    if (!txt) {
        throw new Error("audio.playTxt: 'txt' parameter should not be null")
    }
    if (typeof type !== 'number' || isNaN(type)) {
        throw new Error("audio.playTxt: 'type' parameter should not be null")
    }
    return audioObj.audioPlayTxt(txt, type)
}
 
/**
 * Interrupt currently playing audio
 * @returns {boolean} true if interruption successful, false otherwise
 * 
 * This function immediately stops the currently playing audio without affecting
 * the playback queue. It's useful for emergency stops or when switching
 * between different audio sources.
 */
audio.interrupt = function () {
    return audioObj.audioPlayingInterrupt()
}
 
/**
 * Clear audio playback cache and queue
 * @returns {boolean} true if cache cleared successfully, false otherwise
 * 
 * This function removes all pending audio from the playback queue and clears
 * the audio cache. It should be used when you want to completely reset the
 * audio playback state or free up memory resources.
 * 
 * Note: This operation is mutually exclusive with playback functions and
 * should not be called while audio is actively playing.
 */
audio.clearCache = function () {
    return audioObj.audioClearPlayCache()
}
 
 
function validateNumber(value, name) {
    if (typeof value !== 'number' || isNaN(value)) {
        throw new TypeError(`${name} must be a valid number`);
    }
}
 
// Export audio module as default export
export default audio;