1. 什么是策略模式
策略模式(Strategy Pattern)是一種行為型設計模式,它定義了一系列算法,將每個算法封裝起來,并使它們可以互換。策略模式使得算法的變化獨立于使用算法的客戶。換句話說,策略模式允許在運行時選擇算法的實現,從而提高了代碼的靈活性和可維護性。
策略模式通常包含以下幾個角色:
- 上下文(Context):持有一個策略的引用,并可以在運行時選擇和切換策略。
- 策略接口(Strategy):定義了一個公共接口,用于所有支持的算法。
- 具體策略(ConcreteStrategy):實現策略接口的具體算法。
# 策略接口
class PaymentStrategy:def pay(self, amount):pass# 具體策略:信用卡支付
class CreditCardPayment(PaymentStrategy):def pay(self, amount):return f"Processed credit card payment of ${amount}"# 具體策略:PayPal支付
class PayPalPayment(PaymentStrategy):def pay(self, amount):return f"Processed PayPal payment of ${amount}"# 具體策略:支付寶支付
class AlipayPayment(PaymentStrategy):def pay(self, amount):return f"Processed Alipay payment of ${amount}"# 上下文
class PaymentContext:def __init__(self, strategy: PaymentStrategy):self.strategy = strategydef set_strategy(self, strategy: PaymentStrategy):self.strategy = strategydef execute_payment(self, amount):return self.strategy.pay(amount)if __name__ == "__main__":# 創建不同的支付策略credit_card_payment = CreditCardPayment()paypal_payment = PayPalPayment()alipay_payment = AlipayPayment()# 創建上下文并設置策略payment_context = PaymentContext(credit_card_payment)print(payment_context.execute_payment(100)) # 輸出: Processed credit card payment of $100# 切換策略payment_context.set_strategy(paypal_payment)print(payment_context.execute_payment(200)) # 輸出: Processed PayPal payment of $200# 切換策略payment_context.set_strategy(alipay_payment)print(payment_context.execute_payment(150)) # 輸出: Processed Alipay payment of $150
-
策略接口(PaymentStrategy):定義了支付的公共接口,所有具體支付策略都實現這個接口。它包含一個
pay
方法,接受支付金額作為參數。 -
具體策略(CreditCardPayment、PayPalPayment、AlipayPayment):實現了策略接口的具體支付方式,封裝了各自的支付邏輯。每個具體策略都實現了
pay
方法,提供了不同的支付處理方式。 -
上下文(PaymentContext):持有一個策略的引用,并可以在運行時選擇和切換策略。它通過調用策略的
pay
方法來執行支付。上下文可以在運行時更改策略,從而改變支付方式。
感謝您的耐心和反饋!下面是您提供的完整代碼,已經經過整理和確認,確保它能夠正確實現音頻處理的策略模式,包括總 RMS、最大 RMS、最小 RMS、平均 RMS 和峰值幅度的計算,以及音量調整功能。
2. 示例:音頻處理策略模式
import numpy as np
import librosa
import soundfile as sf# 策略接口
class AudioProcessingStrategy:def calculate_rms(self, audio_data, window_size=None):passdef adjust_volume(self, audio_data, target_rms_dbfs, window_size=None):current_rms_dbfs = self.calculate_rms(audio_data, window_size)return self._adjust_volume(audio_data, target_rms_dbfs, current_rms_dbfs, window_size)@staticmethoddef _adjust_volume(audio_data, target_rms_dbfs, current_rms_dbfs, window_size=None):current_rms = 10 ** (current_rms_dbfs / 20)target_rms = 10 ** (target_rms_dbfs / 20)adjustment_factor = target_rms / current_rms if current_rms > 0 else 1.0return audio_data * adjustment_factor# 具體策略:總 RMS
class TotalRMSStrategy(AudioProcessingStrategy):def calculate_rms(self, audio_data, window_size=None):return 20 * np.log10(np.sqrt(np.mean(audio_data ** 2)) + 1.0e-9)# 具體策略:最大 RMS
class MaxRMSStrategy(AudioProcessingStrategy):def calculate_rms(self, audio_data, window_size=None):rms_values = []for start in range(0, len(audio_data), window_size):end = min(start + window_size, len(audio_data))window = audio_data[start:end]if len(window) > 0:rms = 20 * np.log10(np.sqrt(np.mean(window ** 2)) + 1.0e-9)rms_values.append(rms)return np.max(rms_values) if rms_values else -np.inf# 具體策略:最小 RMS
class MinRMSStrategy(AudioProcessingStrategy):def calculate_rms(self, audio_data, window_size=None):rms_values = []for start in range(0, len(audio_data), window_size):end = min(start + window_size, len(audio_data))window = audio_data[start:end]if len(window) > 0:rms = 20 * np.log10(np.sqrt(np.mean(window ** 2)) + 1.0e-9)rms_values.append(rms)return np.min(rms_values) if rms_values else -np.inf# 具體策略:平均 RMS
class AvgRMSStrategy(AudioProcessingStrategy):def calculate_rms(self, audio_data, window_size=None):rms_values = []for start in range(0, len(audio_data), window_size):end = min(start + window_size, len(audio_data))window = audio_data[start:end]if len(window) > 0:rms = 20 * np.log10(np.sqrt(np.mean(window ** 2)) + 1.0e-9)rms_values.append(rms)return np.mean(rms_values) if rms_values else -np.inf# 具體策略:峰值幅度
class PeakAmplitudeStrategy(AudioProcessingStrategy):def calculate_rms(self, audio_data, window_size=None):return 20 * np.log10(np.max(np.abs(audio_data)) + 1.0e-9)# 上下文
# 上下文
class AudioProcessor:def __init__(self, strategy: AudioProcessingStrategy):self.strategy = strategydef set_strategy(self, strategy: AudioProcessingStrategy):self.strategy = strategyreturn self # 返回自身以支持鏈式調用def calculate_rms(self, audio_data, window_size=None):return self.strategy.calculate_rms(audio_data, window_size)def adjust_volume(self, audio_data, target_rms_dbfs, window_size=None):return self.strategy.adjust_volume(audio_data, target_rms_dbfs, window_size)if __name__ == "__main__":audio_path = './test_volume.wav'audio_data, sr = librosa.load(audio_path, sr=None)# 創建上下文并設置策略audio_processor = AudioProcessor(TotalRMSStrategy())# 計算總 RMS 并調整音量adjusted_audio_total = audio_processor.set_strategy(TotalRMSStrategy()).adjust_volume(audio_data, -20)total_rms = audio_processor.strategy.calculate_rms(audio_data)print(f"Total RMS (dBFS): {total_rms:.2f}")sf.write('./adjusted_audio_total.wav', adjusted_audio_total, sr)# 計算最大 RMS 并調整音量adjusted_audio_max = audio_processor.set_strategy(MaxRMSStrategy()).adjust_volume(audio_data, -20, window_size=1024)max_rms = audio_processor.strategy.calculate_rms(audio_data, window_size=1024)print(f"Max RMS (dBFS): {max_rms:.2f}")sf.write('./adjusted_audio_max.wav', adjusted_audio_max, sr)# 計算最小 RMS 并調整音量adjusted_audio_min = audio_processor.set_strategy(MinRMSStrategy()).adjust_volume(audio_data, -20, window_size=1024)min_rms = audio_processor.strategy.calculate_rms(audio_data, window_size=1024)print(f"Min RMS (dBFS): {min_rms:.2f}")sf.write('./adjusted_audio_min.wav', adjusted_audio_min, sr)# 計算平均 RMS 并調整音量adjusted_audio_avg = audio_processor.set_strategy(AvgRMSStrategy()).adjust_volume(audio_data, -20, window_size=1024)avg_rms = audio_processor.strategy.calculate_rms(audio_data, window_size=1024)print(f"Avg RMS (dBFS): {avg_rms:.2f}")sf.write('./adjusted_audio_avg.wav', adjusted_audio_avg, sr)# 計算峰值幅度并調整音量adjusted_audio_peak = audio_processor.set_strategy(PeakAmplitudeStrategy()).adjust_volume(audio_data, -20)peak_amplitude = audio_processor.strategy.calculate_rms(audio_data)print(f"Peak Amplitude (dBFS): {peak_amplitude:.2f}")sf.write('./adjusted_audio_peak.wav', adjusted_audio_peak, sr)
-
策略接口(AudioProcessingStrategy):定義了計算 RMS 和調整音量的公共接口。
adjust_volume
方法調用calculate_rms
,并且可以選擇性地傳遞window_size
參數。 -
具體策略:
- TotalRMSStrategy:計算總 RMS 并調整音量。
- MaxRMSStrategy:計算最大 RMS 并調整音量。
- MinRMSStrategy:計算最小 RMS 并調整音量。
- AvgRMSStrategy:計算平均 RMS 并調整音量。
- PeakAmplitudeStrategy:計算峰值幅度并調整音量。
-
上下文(AudioProcessor):持有一個策略的引用,并可以在運行時選擇和切換策略。它通過調用策略的方法來處理音頻數據。
-
客戶端代碼:客戶端創建不同的策略,并通過上下文執行音頻處理。客戶端可以在運行時切換策略,靈活應對不同的音頻處理需求。