首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python PyGame 播放聲音完整指南:基礎播放、音效管理、進階控制

     編輯:更多程式設計知識

pygame.mixer 是 Python 遊戲開發與多媒體應用中最常用的聲音播放模組,支援音樂串流播放與音效即時觸發兩種模式。本文系統整理基礎播放流程、音樂 vs 音效差異、常用控制 API、錯誤處理與實戰封裝類別。

核心架構:Music vs Sound

特性pygame.mixer.music (音樂)pygame.mixer.Sound (音效)
用途背景音樂、長音頻短音效、UI 聲音、槍聲
載入方式串流 (不全載入記憶體)完整載入記憶體
同時播放單一軌道 (同一時間只能一首)多通道並發 (預設 8 通道)
格式支援MP3, OGG, MOD 等WAV, OGG (建議 WAV 免解碼)
控制 APIplay, pause, stop, fadeout, set_volumeplay, stop, fadeout, set_volume

最小可行程式(播放音樂)


import pygame

pygame.init()
pygame.mixer.init()

# 載入並播放音樂
pygame.mixer.music.load("background.mp3")
pygame.mixer.music.play()

# 等待播放結束(簡易阻塞)
while pygame.mixer.music.get_busy():
    pygame.time.Clock().tick(10)

pygame.quit()

最小可行程式(播放音效)


import pygame

pygame.init()
pygame.mixer.init()

# 載入音效
shot = pygame.mixer.Sound("shot.wav")

# 觸發播放
shot.play()

# 等待音效結束
while shot.get_num_channels() > 0:
    pygame.time.Clock().tick(10)

pygame.quit()

完整封裝類別:AudioManager


import pygame
import os
from typing import Dict, Optional

class AudioManager:
    """統一管理音樂與音效"""
    
    def __init__(self, frequency=44100, size=-16, channels=2, buffer=512):
        pygame.mixer.pre_init(frequency, size, channels, buffer)
        pygame.mixer.init()
        self.sounds: Dict[str, pygame.mixer.Sound] = {}
        self.music_volume = 0.7
        self.sfx_volume = 1.0
        pygame.mixer.music.set_volume(self.music_volume)
    
    def load_sound(self, name: str, filepath: str) -> bool:
        """載入音效並快取"""
        if not os.path.exists(filepath):
            print(f"[Audio] 檔案不存在: {filepath}")
            return False
        try:
            self.sounds[name] = pygame.mixer.Sound(filepath)
            self.sounds[name].set_volume(self.sfx_volume)
            return True
        except pygame.error as e:
            print(f"[Audio] 載入失敗 {name}: {e}")
            return False
    
    def load_music(self, filepath: str) -> bool:
        """載入背景音樂"""
        if not os.path.exists(filepath):
            print(f"[Audio] 音樂檔案不存在: {filepath}")
            return False
        try:
            pygame.mixer.music.load(filepath)
            pygame.mixer.music.set_volume(self.music_volume)
            return True
        except pygame.error as e:
            print(f"[Audio] 音樂載入失敗: {e}")
            return False
    
    def play_sound(self, name: str, loops: int = 0, maxtime: int = 0, fade_ms: int = 0) -> Optional[pygame.mixer.Channel]:
        """播放音效,回傳 Channel 供後續控制"""
        sound = self.sounds.get(name)
        if not sound:
            print(f"[Audio] 音效未載入: {name}")
            return None
        channel = sound.play(loops, maxtime, fade_ms)
        return channel
    
    def play_music(self, loops: int = -1, start: float = 0.0, fade_ms: int = 0):
        """播放背景音樂,loops=-1 循環播放"""
        pygame.mixer.music.play(loops, start, fade_ms)
    
    def stop_music(self, fade_ms: int = 0):
        pygame.mixer.music.fadeout(fade_ms) if fade_ms else pygame.mixer.music.stop()
    
    def pause_music(self):
        pygame.mixer.music.pause()
    
    def unpause_music(self):
        pygame.mixer.music.unpause()
    
    def set_music_volume(self, volume: float):
        self.music_volume = max(0.0, min(1.0, volume))
        pygame.mixer.music.set_volume(self.music_volume)
    
    def set_sfx_volume(self, volume: float):
        self.sfx_volume = max(0.0, min(1.0, volume))
        for sound in self.sounds.values():
            sound.set_volume(self.sfx_volume)
    
    def stop_all_sounds(self):
        pygame.mixer.stop()
    
    def cleanup(self):
        self.stop_all_sounds()
        pygame.mixer.music.stop()
        self.sounds.clear()
        pygame.mixer.quit()

# === 使用範例 ===
if __name__ == "__main__":
    audio = AudioManager()
    
    # 載入資源
    audio.load_sound("jump", "assets/jump.wav")
    audio.load_sound("coin", "assets/coin.wav")
    audio.load_music("assets/bgm.ogg")
    
    # 播放
    audio.play_music(loops=-1)  # 循環背景音樂
    audio.play_sound("jump")
    
    # 遊戲主迴圈中...
    import time
    time.sleep(5)
    
    audio.cleanup()

進階控制技巧

1. 音效通道控制(同時播放多個同音效、停止特定音效)


# 取得 Channel 物件
channel = sound.play()

# 後續控制該 Channel
channel.set_volume(0.5)
channel.pause()
channel.unpause()
channel.stop()
channel.fadeout(1000)  # 1 秒淡出

# 設定結束回調
def on_sound_end():
    print("音效播放結束")
channel.set_endevent(pygame.USEREVENT + 1)
# 主迴圈中檢查 event.type == pygame.USEREVENT + 1

2. 音樂淡入淡出切換


def crossfade_music(audio_mgr, new_music_path, fade_ms=2000):
    """平滑切換背景音樂"""
    audio_mgr.stop_music(fade_ms)
    # 等待淡出完成(簡易)
    pygame.time.wait(fade_ms)
    audio_mgr.load_music(new_music_path)
    audio_mgr.play_music(fade_ms=fade_ms)

3. 3D 空間音效模擬(簡易立體聲平移)


def play_3d_sound(sound, x_pos, listener_x=0, max_dist=100):
    """
    x_pos: -1.0 (左) 到 1.0 (右)
    簡易立體聲平移
    """
    left_vol = max(0, 1 - x_pos) if x_pos > 0 else 1
    right_vol = max(0, 1 + x_pos) if x_pos < 0 else 1
    # Sound 無直接立體聲控制,需用兩個單聲道 Sound 或 Channel.set_volume
    channel = sound.play()
    if channel:
        # pygame 2.0+ 支援 Channel.set_volume(left, right)
        channel.set_volume(left_vol, right_vol)

4. 即時生成音效(程序化音頻)


import numpy as np

def generate_tone(freq=440, duration=0.5, volume=0.5, sample_rate=44100):
    """生成正弦波音效"""
    t = np.linspace(0, duration, int(sample_rate * duration), False)
    wave = np.sin(2 * np.pi * freq * t) * volume * 32767
    wave = wave.astype(np.int16)
    # 轉為雙聲道
    stereo = np.column_stack((wave, wave))
    return pygame.mixer.Sound(buffer=stereo.tobytes())

# 使用
tone = generate_tone(880, 0.3)
tone.play()

支援格式與編碼建議

格式用途優點缺點
WAV (PCM)音效免解碼、延遲極低、相容性最好檔案大
OGG Vorbis音樂/音效壓縮率高、開源、支援循環點需解碼、略有延遲
MP3音樂通用、壓縮率高授權問題、不支援無縫循環
FLAC音樂無損壓縮解碼較慢、不支援循環

建議:音效用 WAV (16-bit, 44.1kHz, mono),音樂用 OGG。

常見問題與解決

問題原因解決
無聲音未呼叫 pygame.mixer.init()、音量為 0、裝置被佔用檢查 init 順序、音量設定、關閉其他播放器
音效延遲用 music 播放短音效、格式需解碼(MP3/OGG)音效用 Sound + WAV、預載入快取
同時播放截斷通道數不足 (預設 8)pygame.mixer.set_num_channels(32)
MP3 不支援系統缺少 MP3 解碼器改用 OGG、安裝 libmpg123
程式結束聲音截斷未等待播放完成用 while get_busy() 等待或設定 endevent

總結

PyGame 声音播放核心:音樂用 mixer.music (串流、單軌)、音效用 mixer.Sound (記憶體、多通道)。關鍵最佳實務:pre_init 設定參數、WAV 格式音效、快取 Sound 物件、Channel 精確控制、fadeout 平滑切換。封裝 AudioManager 類別可統一資源管理、音量控制、生命週期,是遊戲與多媒體專案的標準做法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved