1use crate::prelude::*;
7use std::alloc::{GlobalAlloc, Layout, System};
8use std::collections::{BTreeMap, HashMap, VecDeque};
9use std::sync::{
10 atomic::{AtomicUsize, Ordering},
11 Arc, Mutex, RwLock,
12};
13use std::thread;
14use std::time::{Duration, Instant};
15
16#[derive(Debug)]
18pub struct AudioBufferPool {
19 small_buffers: Arc<Mutex<Vec<Vec<f32>>>>, medium_buffers: Arc<Mutex<Vec<Vec<f32>>>>, large_buffers: Arc<Mutex<Vec<Vec<f32>>>>, stats: Arc<Mutex<PoolStats>>,
23}
24
25#[derive(Debug, Default, Clone)]
27pub struct PoolStats {
28 small_hits: usize,
29 small_misses: usize,
30 medium_hits: usize,
31 medium_misses: usize,
32 large_hits: usize,
33 large_misses: usize,
34}
35
36impl Default for AudioBufferPool {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl AudioBufferPool {
43 pub fn new() -> Self {
45 Self {
46 small_buffers: Arc::new(Mutex::new(Vec::with_capacity(10))),
47 medium_buffers: Arc::new(Mutex::new(Vec::with_capacity(5))),
48 large_buffers: Arc::new(Mutex::new(Vec::with_capacity(2))),
49 stats: Arc::new(Mutex::new(PoolStats::default())),
50 }
51 }
52
53 pub fn get_buffer(&self, min_size: usize) -> Vec<f32> {
55 let category = self.categorize_size(min_size);
56
57 match category {
58 BufferCategory::Small => {
59 let mut buffers = self
60 .small_buffers
61 .lock()
62 .expect("Small buffers lock poisoned");
63 if let Some(mut buffer) = buffers.pop() {
64 if buffer.capacity() >= min_size {
65 buffer.clear();
66 buffer.resize(min_size, 0.0);
67 self.stats.lock().expect("Stats lock poisoned").small_hits += 1;
68 return buffer;
69 } else {
70 buffers.push(buffer);
72 }
73 }
74 self.stats.lock().expect("Stats lock poisoned").small_misses += 1;
75 let mut buffer = Vec::with_capacity(std::cmp::max(min_size, 22050)); buffer.resize(min_size, 0.0);
77 buffer
78 }
79 BufferCategory::Medium => {
80 let mut buffers = self
81 .medium_buffers
82 .lock()
83 .expect("Medium buffers lock poisoned");
84 if let Some(mut buffer) = buffers.pop() {
85 if buffer.capacity() >= min_size {
86 buffer.clear();
87 buffer.resize(min_size, 0.0);
88 self.stats.lock().expect("Stats lock poisoned").medium_hits += 1;
89 return buffer;
90 } else {
91 buffers.push(buffer);
92 }
93 }
94 self.stats
95 .lock()
96 .expect("Stats lock poisoned")
97 .medium_misses += 1;
98 Vec::with_capacity(std::cmp::max(min_size, 110250)) }
100 BufferCategory::Large => {
101 let mut buffers = self
102 .large_buffers
103 .lock()
104 .expect("Large buffers lock poisoned");
105 if let Some(mut buffer) = buffers.pop() {
106 if buffer.capacity() >= min_size {
107 buffer.clear();
108 buffer.resize(min_size, 0.0);
109 self.stats.lock().expect("Stats lock poisoned").large_hits += 1;
110 return buffer;
111 } else {
112 buffers.push(buffer);
113 }
114 }
115 self.stats.lock().expect("Stats lock poisoned").large_misses += 1;
116 Vec::with_capacity(min_size)
117 }
118 }
119 }
120
121 pub fn return_buffer(&self, buffer: Vec<f32>) {
123 let category = self.categorize_size(buffer.capacity());
124
125 match category {
126 BufferCategory::Small => {
127 let mut buffers = self
128 .small_buffers
129 .lock()
130 .expect("Small buffers lock poisoned");
131 if buffers.len() < 10 {
132 buffers.push(buffer);
134 }
135 }
136 BufferCategory::Medium => {
137 let mut buffers = self
138 .medium_buffers
139 .lock()
140 .expect("Medium buffers lock poisoned");
141 if buffers.len() < 5 {
142 buffers.push(buffer);
143 }
144 }
145 BufferCategory::Large => {
146 let mut buffers = self
147 .large_buffers
148 .lock()
149 .expect("Large buffers lock poisoned");
150 if buffers.len() < 2 {
151 buffers.push(buffer);
152 }
153 }
154 }
155 }
156
157 fn categorize_size(&self, size: usize) -> BufferCategory {
158 if size <= 22050 {
159 BufferCategory::Small
161 } else if size <= 110250 {
162 BufferCategory::Medium
164 } else {
165 BufferCategory::Large
166 }
167 }
168
169 pub fn get_stats(&self) -> PoolStats {
171 self.stats.lock().expect("Stats lock poisoned").clone()
172 }
173}
174
175impl PoolStats {
176 fn hit_rate(&self) -> f64 {
177 let total_hits = self.small_hits + self.medium_hits + self.large_hits;
178 let total_requests =
179 total_hits + self.small_misses + self.medium_misses + self.large_misses;
180
181 if total_requests == 0 {
182 0.0
183 } else {
184 total_hits as f64 / total_requests as f64
185 }
186 }
187}
188
189#[derive(Debug)]
191enum BufferCategory {
192 Small,
194 Medium,
196 Large,
198}
199
200#[derive(Debug)]
202pub struct SmallAudioOptimizer {
203 buffer_pool: AudioBufferPool,
204 small_sample_cache: Arc<Mutex<HashMap<String, CachedResult>>>,
205}
206
207#[derive(Debug, Clone)]
209struct CachedResult {
210 result: Vec<f32>,
211 timestamp: Instant,
212 access_count: usize,
213}
214
215impl Default for SmallAudioOptimizer {
216 fn default() -> Self {
217 Self::new()
218 }
219}
220
221impl SmallAudioOptimizer {
222 pub fn new() -> Self {
224 Self {
225 buffer_pool: AudioBufferPool::new(),
226 small_sample_cache: Arc::new(Mutex::new(HashMap::new())),
227 }
228 }
229
230 pub fn optimize_small_conversion(
232 &self,
233 audio: &[f32],
234 conversion_type: &ConversionType,
235 target: &ConversionTarget,
236 ) -> Option<Vec<f32>> {
237 if audio.len() > 11025 {
239 return None;
241 }
242
243 let cache_key = self.create_cache_key(audio, conversion_type, target);
245
246 if let Some(cached) = self.get_cached_result(&cache_key) {
248 return Some(cached);
249 }
250
251 let optimized_result = match conversion_type {
253 ConversionType::PitchShift => self.fast_pitch_shift(audio, target),
254 ConversionType::SpeedTransformation => self.fast_speed_transform(audio, target),
255 ConversionType::PassThrough => {
256 Some(audio.to_vec())
258 }
259 _ => None, };
261
262 if let Some(ref result) = optimized_result {
264 self.cache_result(cache_key, result.clone());
265 }
266
267 optimized_result
268 }
269
270 fn create_cache_key(
271 &self,
272 audio: &[f32],
273 conversion_type: &ConversionType,
274 target: &ConversionTarget,
275 ) -> String {
276 use std::collections::hash_map::DefaultHasher;
277 use std::hash::{Hash, Hasher};
278
279 let mut hasher = DefaultHasher::new();
280
281 let audio_hash = if audio.len() <= 100 {
283 audio
285 .iter()
286 .fold(0u64, |acc, &x| acc.wrapping_add((x * 1000.0) as u64))
287 } else {
288 audio
290 .iter()
291 .step_by(audio.len() / 20)
292 .fold(0u64, |acc, &x| acc.wrapping_add((x * 1000.0) as u64))
293 };
294
295 audio_hash.hash(&mut hasher);
296 conversion_type.hash(&mut hasher);
297
298 match conversion_type {
300 ConversionType::PitchShift => {
301 (target.characteristics.pitch.mean_f0 as u32).hash(&mut hasher);
302 }
303 ConversionType::SpeedTransformation => {
304 ((target.characteristics.timing.speaking_rate * 1000.0) as u32).hash(&mut hasher);
305 }
306 _ => {}
307 }
308
309 format!("small_audio_{}", hasher.finish())
310 }
311
312 fn get_cached_result(&self, key: &str) -> Option<Vec<f32>> {
313 let mut cache = self
314 .small_sample_cache
315 .lock()
316 .expect("Sample cache lock poisoned");
317
318 if let Some(cached) = cache.get_mut(key) {
319 if cached.timestamp.elapsed() < Duration::from_secs(300) {
321 cached.access_count += 1;
322 return Some(cached.result.clone());
323 } else {
324 cache.remove(key);
326 }
327 }
328 None
329 }
330
331 fn cache_result(&self, key: String, result: Vec<f32>) {
332 let mut cache = self
333 .small_sample_cache
334 .lock()
335 .expect("Sample cache lock poisoned");
336
337 if cache.len() >= 100 {
339 let mut entries: Vec<_> = cache
341 .iter()
342 .map(|(k, v)| (k.clone(), v.timestamp))
343 .collect();
344 entries.sort_by_key(|(_, timestamp)| *timestamp);
345
346 for (k, _) in entries.iter().take(10) {
348 cache.remove(k);
349 }
350 }
351
352 cache.insert(
353 key,
354 CachedResult {
355 result,
356 timestamp: Instant::now(),
357 access_count: 1,
358 },
359 );
360 }
361
362 fn fast_pitch_shift(&self, audio: &[f32], target: &ConversionTarget) -> Option<Vec<f32>> {
363 let target_f0 = target.characteristics.pitch.mean_f0;
364 let base_f0 = 220.0; let ratio = target_f0 / base_f0;
366
367 let output_len = audio.len();
369 let mut result = self.buffer_pool.get_buffer(output_len);
370
371 for (i, result_item) in result.iter_mut().enumerate().take(output_len) {
372 let src_index = (i as f32 * ratio) as usize;
373 if src_index < audio.len() {
374 *result_item = audio[src_index];
375 } else {
376 *result_item = 0.0;
377 }
378 }
379
380 Some(result)
381 }
382
383 fn fast_speed_transform(&self, audio: &[f32], target: &ConversionTarget) -> Option<Vec<f32>> {
384 let speed_ratio = target.characteristics.timing.speaking_rate;
385 let output_len = (audio.len() as f32 / speed_ratio) as usize;
386
387 let mut result = self.buffer_pool.get_buffer(output_len);
388
389 for (i, result_item) in result.iter_mut().enumerate().take(output_len) {
390 let src_index = (i as f32 * speed_ratio) as usize;
391 if src_index < audio.len() {
392 *result_item = audio[src_index];
393 } else {
394 *result_item = 0.0;
395 }
396 }
397
398 Some(result)
399 }
400
401 pub fn get_pool_stats(&self) -> PoolStats {
403 self.buffer_pool.get_stats()
404 }
405
406 pub fn clear_cache(&self) {
408 self.small_sample_cache
409 .lock()
410 .expect("Sample cache lock poisoned")
411 .clear();
412 }
413}
414
415#[derive(Debug)]
417pub struct ConversionPerformanceMonitor {
418 conversion_times: Arc<Mutex<Vec<Duration>>>,
419 memory_usage: Arc<Mutex<Vec<usize>>>,
420 start_time: Option<Instant>,
421}
422
423impl Default for ConversionPerformanceMonitor {
424 fn default() -> Self {
425 Self::new()
426 }
427}
428
429impl ConversionPerformanceMonitor {
430 pub fn new() -> Self {
432 Self {
433 conversion_times: Arc::new(Mutex::new(Vec::new())),
434 memory_usage: Arc::new(Mutex::new(Vec::new())),
435 start_time: None,
436 }
437 }
438
439 pub fn start_timing(&mut self) {
441 self.start_time = Some(Instant::now());
442 }
443
444 pub fn end_timing(&mut self) {
446 if let Some(start) = self.start_time.take() {
447 let duration = start.elapsed();
448 self.conversion_times
449 .lock()
450 .expect("Conversion times lock poisoned")
451 .push(duration);
452 }
453 }
454
455 pub fn record_memory_usage(&self, bytes: usize) {
457 self.memory_usage
458 .lock()
459 .expect("Memory usage lock poisoned")
460 .push(bytes);
461 }
462
463 pub fn get_average_conversion_time(&self) -> Duration {
465 let times = self
466 .conversion_times
467 .lock()
468 .expect("Conversion times lock poisoned");
469 if times.is_empty() {
470 Duration::from_millis(0)
471 } else {
472 let total_nanos: u64 = times.iter().map(|d| d.as_nanos() as u64).sum();
473 Duration::from_nanos(total_nanos / times.len() as u64)
474 }
475 }
476
477 pub fn get_memory_stats(&self) -> (usize, usize, f64) {
479 let usage = self
480 .memory_usage
481 .lock()
482 .expect("Memory usage lock poisoned");
483 if usage.is_empty() {
484 (0, 0, 0.0)
485 } else {
486 let min = *usage.iter().min().expect("Memory usage is not empty");
487 let max = *usage.iter().max().expect("Memory usage is not empty");
488 let avg = usage.iter().sum::<usize>() as f64 / usage.len() as f64;
489 (min, max, avg)
490 }
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 #[test]
499 fn test_audio_buffer_pool() {
500 let pool = AudioBufferPool::new();
501
502 let buffer1 = pool.get_buffer(1000);
504 assert!(buffer1.capacity() >= 1000);
505
506 pool.return_buffer(buffer1);
507
508 let buffer2 = pool.get_buffer(500);
510 assert!(buffer2.capacity() >= 500);
511
512 let stats = pool.get_stats();
513 assert!(stats.hit_rate() > 0.0);
514 }
515
516 #[test]
517 fn test_small_audio_optimizer() {
518 let optimizer = SmallAudioOptimizer::new();
519
520 let audio: Vec<f32> = (0..1000)
522 .map(|i| (i as f32 * 440.0 * 2.0 * std::f32::consts::PI / 22050.0).sin() * 0.1)
523 .collect();
524
525 let mut target_chars = VoiceCharacteristics::default();
526 target_chars.pitch.mean_f0 = 880.0;
527 let target = ConversionTarget::new(target_chars);
528
529 let result =
531 optimizer.optimize_small_conversion(&audio, &ConversionType::PitchShift, &target);
532 assert!(result.is_some());
533
534 let result2 =
536 optimizer.optimize_small_conversion(&audio, &ConversionType::PitchShift, &target);
537 assert!(result2.is_some());
538 }
539
540 #[test]
541 fn test_performance_monitor() {
542 let mut monitor = ConversionPerformanceMonitor::new();
543
544 monitor.start_timing();
545 std::thread::sleep(Duration::from_millis(10));
546 monitor.end_timing();
547
548 monitor.record_memory_usage(1024);
549 monitor.record_memory_usage(2048);
550
551 let avg_time = monitor.get_average_conversion_time();
552 assert!(avg_time.as_millis() >= 10);
553
554 let (min_mem, max_mem, avg_mem) = monitor.get_memory_stats();
555 assert_eq!(min_mem, 1024);
556 assert_eq!(max_mem, 2048);
557 assert_eq!(avg_mem, 1536.0);
558 }
559}