veza/veza-stream-server/src/codecs/flac.rs
senke 7af9c98a73 style(stream-server): apply rustfmt and fix golangci-lint v2 install
Two fixes surfaced by run #55:

1. veza-stream-server (47 files): cargo fmt had been run locally but
   never committed — the working tree was clean locally while HEAD
   had unformatted code. CI's `cargo fmt -- --check` caught the drift.
   This commit lands the formatting that was already staged.

2. ci.yml Install Go tools: `go install .../cmd/golangci-lint@latest`
   resolves to v1.64.8 (the old /cmd/ module path). The repo's
   .golangci.yml is v2-format, so v1 refuses with:
     "you are using a configuration file for golangci-lint v2
      with golangci-lint v1: please use golangci-lint v2"
   Switch to the /v2/cmd/ path so @latest actually gets v2.x.
2026-04-14 15:30:32 +02:00

203 lines
6 KiB
Rust

use crate::codecs::{
AudioDecoder, AudioEncoder, DecodedAudio, DecoderConfig, DecoderInfo, EncoderConfig,
EncoderInfo, EncoderMetrics,
};
use crate::error::AppError;
use std::time::Instant;
/// Implémentation FLAC Encoder
#[derive(Debug)]
pub struct FlacEncoderImpl {
config: EncoderConfig,
metrics: EncoderMetrics,
compression_level: u8,
block_size: u16,
sample_count: u64,
frame_count: u64,
start_time: Instant,
}
impl FlacEncoderImpl {
pub fn new(config: EncoderConfig) -> Result<Self, AppError> {
let compression_level = match config.quality {
crate::codecs::CodecQuality::Low => 1,
crate::codecs::CodecQuality::Medium => 3,
crate::codecs::CodecQuality::High => 5,
crate::codecs::CodecQuality::VeryHigh => 8,
crate::codecs::CodecQuality::Custom(level) => (level * 8.0) as u8,
};
Ok(Self {
config,
metrics: EncoderMetrics::default(),
compression_level,
block_size: 4096,
sample_count: 0,
frame_count: 0,
start_time: Instant::now(),
})
}
}
impl AudioEncoder for FlacEncoderImpl {
fn encode(
&mut self,
samples: &[f32],
_sample_rate: u32,
_channels: u8,
) -> Result<Vec<u8>, AppError> {
let start_time = Instant::now();
// Simulation d'encodage FLAC
let samples_per_channel = samples.len() / self.config.channels as usize;
let estimated_size = samples_per_channel * 2; // Estimation compression ratio 2:1
let mut output = Vec::with_capacity(estimated_size);
// Header FLAC simplifié
if self.frame_count == 0 {
output.extend_from_slice(b"fLaC");
output.extend_from_slice(&[0x00, 0x00, 0x00, 0x22]); // STREAMINFO block
}
// Frame data simulation
for chunk in samples.chunks(self.block_size as usize) {
let compressed_size = chunk.len() / 2; // Simulation compression lossless
output.extend(vec![0u8; compressed_size]);
}
// Mettre à jour métriques
self.metrics.frames_encoded += 1;
self.metrics.bytes_output += output.len() as u64;
self.metrics.encoding_time_ms += start_time.elapsed().as_millis() as u64;
self.frame_count += 1;
self.sample_count += samples_per_channel as u64;
Ok(output)
}
fn finalize(&mut self) -> Result<Vec<u8>, AppError> {
self.metrics.compression_ratio = if self.sample_count > 0 {
let input_size = self.sample_count * self.config.channels as u64 * 4;
input_size as f32 / self.metrics.bytes_output as f32
} else {
1.5 // Typical FLAC compression ratio
};
self.metrics.quality_score = 1.0; // Lossless = perfect quality
Ok(Vec::new())
}
fn reset(&mut self) -> Result<(), AppError> {
self.metrics = EncoderMetrics::default();
self.sample_count = 0;
self.frame_count = 0;
self.start_time = Instant::now();
Ok(())
}
fn set_bitrate(&mut self, _bitrate: u32) -> Result<(), AppError> {
Ok(()) // FLAC est lossless, pas de bitrate fixe
}
fn info(&self) -> EncoderInfo {
EncoderInfo {
codec_name: "FLAC".to_string(),
version: "1.3.4-simulation".to_string(),
bitrate: 0, // Variable
sample_rate: self.config.sample_rate,
channels: self.config.channels,
bit_depth: 16,
frame_size: self.block_size as usize,
latency_ms: 40.0,
quality_mode: format!("Compression Level {}", self.compression_level),
}
}
fn metrics(&self) -> EncoderMetrics {
self.metrics.clone()
}
}
/// Implémentation FLAC Decoder
#[derive(Debug)]
pub struct FlacDecoderImpl {
config: DecoderConfig,
frame_count: u64,
sample_count: u64,
}
impl FlacDecoderImpl {
pub fn new(config: DecoderConfig) -> Result<Self, AppError> {
Ok(Self {
config,
frame_count: 0,
sample_count: 0,
})
}
}
impl AudioDecoder for FlacDecoderImpl {
fn decode(&mut self, data: &[u8]) -> Result<DecodedAudio, AppError> {
// Simulation de décodage FLAC
let samples_per_channel = 4096; // Block size typique
let total_samples = samples_per_channel * self.config.channels as usize;
// Simulation : générer des échantillons basés sur les données d'entrée
let mut samples = Vec::with_capacity(total_samples);
for i in 0..total_samples {
let value = if !data.is_empty() {
(data[i % data.len()] as f32 - 128.0) / 128.0
} else {
0.0
};
samples.push(value * 0.1); // Amplitude réduite
}
self.frame_count += 1;
self.sample_count += samples_per_channel as u64;
let duration_ms =
(samples_per_channel as f32 / self.config.sample_rate as f32 * 1000.0) as u32;
Ok(DecodedAudio {
samples,
sample_rate: self.config.sample_rate,
channels: self.config.channels,
duration_ms,
format: self.config.output_format.clone(),
})
}
fn reset(&mut self) -> Result<(), AppError> {
self.frame_count = 0;
self.sample_count = 0;
Ok(())
}
fn info(&self) -> DecoderInfo {
DecoderInfo {
codec_name: "FLAC".to_string(),
version: "1.3.4-simulation".to_string(),
sample_rate: self.config.sample_rate,
channels: self.config.channels,
bit_depth: 16,
frame_size: 4096,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_flac_encoder() {
let config = EncoderConfig::default();
let mut encoder = FlacEncoderImpl::new(config).unwrap();
let samples = vec![0.1, -0.1, 0.2, -0.2];
let result = encoder.encode(&samples, 44100, 2);
assert!(result.is_ok());
}
}