【Pygame】mixer.Sound.stop()徹底解説!エラーと解決策、応用例

2025-05-31

Pygameの音声機能には、主に以下の2種類があります。

  1. pygame.mixer.music: 主にBGM(背景音楽)のような、比較的長い音楽ファイルを再生するために使われます。ループ再生やフェードイン/アウトなどの機能が充実しています。pygame.mixer.music.stop() でBGMを停止します。
  2. pygame.mixer.Sound: 効果音(SE)のような、短い音を再生するために使われます。銃声、コインの取得音、ジャンプ音など、ゲーム内で頻繁に再生される音に適しています。

mixer.Sound.stop() の使い方

mixer.Sound.stop() メソッドは、pygame.mixer.Sound オブジェクトに対して呼び出します。


import pygame

# Pygameの初期化
pygame.init()

# ミキサーの初期化
pygame.mixer.init()

# 効果音ファイルの読み込み
# (例として'coin_sound.wav'というファイルがあると仮定)
try:
    coin_sound = pygame.mixer.Sound('coin_sound.wav')
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    pygame.quit()
    exit()

# 効果音を再生
coin_sound.play()

# 任意の処理(例: 2秒間待つ)
pygame.time.wait(2000)

# 効果音を停止
coin_sound.stop()

# Pygameの終了
pygame.quit()
  1. pygame.mixer.Sound('coin_sound.wav') で、指定した音声ファイル(例: coin_sound.wav)から Sound オブジェクトを作成します。
  2. coin_sound.play() で、その効果音を再生します。
  3. coin_sound.stop() を呼び出すと、現在再生中の coin_sound オブジェクトの再生が直ちに停止します。
  • フェードアウト: mixer.Sound には fadeout() メソッドもあります。これは音量を徐々に下げながら停止させる場合に便利です。
  • BGMとの違い: pygame.mixer.music.stop() と混同しないように注意してください。mixer.Sound.stop() は効果音用、pygame.mixer.music.stop() はBGM用です。
  • 特定のSoundオブジェクトに作用: mixer.Sound.stop() は、そのメソッドを呼び出した Sound オブジェクトの再生のみを停止します。もし複数の Sound オブジェクトが同時に再生されている場合、他の Sound オブジェクトの再生には影響しません。
  • 即時停止: stop() メソッドは、呼び出されるとすぐに音の再生を停止します。


一般的なエラーと問題点

    • 原因: 効果音が非常に短く、再生開始直後に stop() を呼び出すと、Pygameの内部処理のタイミングによっては一瞬音が聞こえてしまうことがあります。また、mixer.Sound の仕様上、完全に停止するまでに微細な遅延が生じる場合があります。

    • 解決策:

      • fadeout() の使用: より滑らかに音を停止させたい場合は、sound.fadeout(milliseconds) を使用します。これにより、指定した時間(ミリ秒)をかけて徐々に音量が下がり、最終的に停止します。
      # 100ミリ秒かけてフェードアウト
      sound.fadeout(100) 
      
      • 音量調整: sound.set_volume(0) で音量をゼロに設定し、実質的に聞こえなくする方法もあります。
      sound.set_volume(0)
      # 必要であれば、後で stop() を呼ぶか、オブジェクトを破棄する
      
  1. 複数の音が同時に再生されている場合、意図しない音が停止してしまう

    • 原因: mixer.Sound.stop() は、その Sound オブジェクトの再生を停止します。もし同じ Sound オブジェクトを複数回 play() していて、それらが別々のチャンネルで再生されている場合、どの再生が停止されるかは保証されません。一般的には、最後に再生されたインスタンスが停止されることが多いですが、確実ではありません。

    • 解決策:

      • チャンネルの管理: 複数の同じ効果音を同時に再生し、個別に停止したい場合は、pygame.mixer.Channel を使用してチャンネルを明示的に管理します。
      channel = pygame.mixer.find_channel() # 空いているチャンネルを探す
      if channel:
          channel.play(sound)
          # その後、この特定のチャンネルの音を停止
          # channel.stop()
      
      • 異なるSoundオブジェクトを使用: それぞれの再生に対して新しい Sound オブジェクトを作成することも考えられますが、リソースの消費が増える可能性があります。
  • Pygameのバージョン: Pygameのバージョンによっては、特定のOSやファイル形式で問題が発生する場合があります。必要であれば、Pygameを更新またはダウングレードすることも検討します。
  • 他の音声ファイルの試行: 別の .wav ファイルや .ogg ファイルを試して、ファイル自体に問題がないか確認します。
  • 音量設定の確認: pygame.mixer.Sound.set_volume() で音量がゼロになっていないか確認します。また、システムの音量設定も確認してください。
  • ファイルパスのデバッグ: print(os.path.abspath("your_sound_file.wav")) のようにして、実際にPygameが探しているファイルパスを確認します。
  • 最小限のコードで再現: 問題が発生している部分だけを切り出し、できるだけ短いコードで問題を再現してみてください。これにより、問題の原因を特定しやすくなります。
  • エラーメッセージの確認: Pythonのトレースバック(エラーメッセージ)を注意深く読み、どの行で何が問題になっているのかを把握します。
  • 初期化の確認: pygame.mixer.get_init() を使用して、ミキサーが正しく初期化されているか確認できます。初期化されていれば、(frequency, format, channels) のタプルが返されます。


例1: 基本的な再生と停止

この例では、効果音を再生し、数秒後に停止します。

import pygame
import time

# 1. Pygameの初期化
pygame.init()

# 2. ミキサーの初期化 (Soundオブジェクトを使用するために必須)
# デフォルト設定 (44100 Hz, -16ビット, 2チャンネル) で十分なことが多い
pygame.mixer.init() 

# 3. 画面の設定 (イベントループを動かすために必要)
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Sound Stop Example 1")

# 4. 効果音ファイルの読み込み
# ここでは「sample.wav」というファイルが存在すると仮定します。
# 適切なWAVまたはOGGファイルを準備してください。
try:
    sound_effect = pygame.mixer.Sound("sample.wav")
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    print("「sample.wav」というファイルをこのスクリプトと同じディレクトリに置いてください。")
    pygame.quit()
    exit()

print("効果音を再生します...")
# 5. 効果音の再生
sound_effect.play()

# 6. メインループ
running = True
start_time = time.time() # 再生開始時刻を記録

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 7. 3秒後に効果音を停止
    if time.time() - start_time > 3:
        print("効果音を停止します...")
        sound_effect.stop() # ここでSoundオブジェクトの再生を停止
        running = False # プログラムを終了

    # 短い遅延 (CPU使用率を抑えるため)
    pygame.time.delay(10) 

# 8. Pygameの終了
pygame.quit()
print("プログラムが終了しました。")

解説:

  • pygame.quit() は、プログラムを終了する前にPygameのモジュールを適切に解放します。
  • time.time() を使って再生開始からの時間を計測し、指定時間が経過したら sound_effect.stop() を呼び出して再生を停止します。
  • sound_effect.play() で音の再生を開始します。
  • pygame.mixer.init() は、pygame.mixer.Sound を使う上で必須です。

例2: キー入力による再生と停止

この例では、スペースキーを押すと効果音が再生され、もう一度スペースキーを押すと停止します。

import pygame

# 1. Pygameの初期化
pygame.init()
pygame.mixer.init()

# 2. 画面の設定
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Sound Control by Key Press")
font = pygame.font.Font(None, 36)

# 3. 効果音ファイルの読み込み
try:
    shoot_sound = pygame.mixer.Sound("shoot.wav") # 例: 銃声など
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    print("「shoot.wav」というファイルをこのスクリプトと同じディレクトリに置いてください。")
    pygame.quit()
    exit()

# 4. 効果音の再生状態を管理する変数
is_playing = False
sound_channel = None # どのチャンネルで再生されているかを保持する変数

# 5. メインループ
running = True
message = "Press SPACE to Play/Stop Sound"

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                if not is_playing:
                    # 再生中でなければ再生開始
                    print("Sound Playing...")
                    # play()はChannelオブジェクトを返すことがあるので、それを保持しておくと良い
                    sound_channel = shoot_sound.play() 
                    is_playing = True
                    message = "Playing... Press SPACE to Stop"
                else:
                    # 再生中であれば停止
                    print("Sound Stopping...")
                    shoot_sound.stop() # 現在再生中のSoundオブジェクトを停止
                    is_playing = False
                    message = "Sound Stopped. Press SPACE to Play"

    # 画面描画
    screen.fill((0, 0, 0)) # 黒で塗りつぶし
    text_surface = font.render(message, True, (255, 255, 255)) # 白い文字
    text_rect = text_surface.get_rect(center=(300, 200))
    screen.blit(text_surface, text_rect)
    pygame.display.flip()

    # 短い遅延
    pygame.time.delay(10)

# 6. Pygameの終了
pygame.quit()
print("プログラムが終了しました。")

解説:

  • font.render()screen.blit() を使って、画面にメッセージを表示しています。
  • shoot_sound.play() で再生を開始し、shoot_sound.stop() で停止します。
  • is_playing というブール変数を使って、現在音が再生中かどうかを追跡します。
  • pygame.KEYDOWN イベントでスペースキーが押されたかを検出します。

この例では、異なる効果音を再生し、特定のキーで特定の音を停止します。

import pygame
import time

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

screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Multiple Sounds Control")
font = pygame.font.Font(None, 30)

# 複数の効果音ファイルを読み込む
try:
    sound_a = pygame.mixer.Sound("sound_a.wav")
    sound_b = pygame.mixer.Sound("sound_b.wav")
    sound_c = pygame.mixer.Sound("sound_c.wav")
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    print("「sound_a.wav」「sound_b.wav」「sound_c.wav」を準備してください。")
    pygame.quit()
    exit()

# 各サウンドの再生状態を管理するディクショナリ
sound_states = {
    'A': {'sound': sound_a, 'playing': False},
    'B': {'sound': sound_b, 'playing': False},
    'C': {'sound': sound_c, 'playing': False},
}

# 案内メッセージ
messages = [
    "Press A to Play/Stop Sound A",
    "Press B to Play/Stop Sound B",
    "Press C to Play/Stop Sound C",
    "---",
    "Current Status:"
]

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                if not sound_states['A']['playing']:
                    print("Playing Sound A...")
                    sound_states['A']['sound'].play()
                    sound_states['A']['playing'] = True
                else:
                    print("Stopping Sound A...")
                    sound_states['A']['sound'].stop() # Sound Aを停止
                    sound_states['A']['playing'] = False
            
            elif event.key == pygame.K_b:
                if not sound_states['B']['playing']:
                    print("Playing Sound B...")
                    sound_states['B']['sound'].play()
                    sound_states['B']['playing'] = True
                else:
                    print("Stopping Sound B...")
                    sound_states['B']['sound'].stop() # Sound Bを停止
                    sound_states['B']['playing'] = False
            
            elif event.key == pygame.K_c:
                if not sound_states['C']['playing']:
                    print("Playing Sound C...")
                    sound_states['C']['sound'].play()
                    sound_states['C']['playing'] = True
                else:
                    print("Stopping Sound C...")
                    sound_states['C']['sound'].stop() # Sound Cを停止
                    sound_states['C']['playing'] = False

    # 画面描画
    screen.fill((0, 0, 0))
    
    y_offset = 20
    for msg in messages:
        text_surface = font.render(msg, True, (255, 255, 255))
        screen.blit(text_surface, (20, y_offset))
        y_offset += 30

    # 各サウンドの現在の状態を表示
    y_offset += 20 # 区切り
    for key, state in sound_states.items():
        status_text = f"Sound {key}: {'Playing' if state['playing'] else 'Stopped'}"
        text_surface = font.render(status_text, True, (0, 255, 0) if state['playing'] else (255, 0, 0))
        screen.blit(text_surface, (20, y_offset))
        y_offset += 30

    pygame.display.flip()
    pygame.time.delay(10)

pygame.quit()
print("プログラムが終了しました。")

解説:

  • キー入力に応じて、対応する Sound オブジェクトの play() または stop() を呼び出します。これにより、他の音が再生されていても、特定の音だけを停止できます。
  • ディクショナリ sound_states を使って、各 Sound オブジェクトとその再生状態を管理します。
  • sound_a, sound_b, sound_c という3つの異なる Sound オブジェクトを作成します。


mixer.Sound.fadeout(time)

stop() が音を瞬時に停止するのに対し、fadeout() は音量を徐々に減衰させながら停止します。これにより、より自然な音の終了を実現できます。

  • 用途: 爆発音の余韻を消す、オブジェクトが消滅する際の音の終焉、ゲームオーバー時の効果音など、急な中断ではなく、滑らかに音を消したい場合に適しています。
  • 機能: 指定された時間(ミリ秒単位)をかけて、Sound オブジェクトの音量をゼロにフェードアウトさせ、その後停止します。


import pygame
import time

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

screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Sound Fadeout Example")

try:
    explosion_sound = pygame.mixer.Sound("explosion.wav")
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    print("「explosion.wav」というファイルをこのスクリプトと同じディレクトリに置いてください。")
    pygame.quit()
    exit()

print("効果音を再生します。5秒後にフェードアウトを開始します。")
explosion_sound.play()

running = True
start_time = time.time()

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 5秒後にフェードアウトを開始
    if time.time() - start_time > 5:
        print("効果音を500ミリ秒かけてフェードアウトします...")
        explosion_sound.fadeout(500) # 0.5秒かけてフェードアウト
        start_time = float('inf') # これ以上フェードアウト処理が呼ばれないようにする

    # フェードアウトが完全に終了したか、または音が停止したかを確認
    # is_playing() はSoundオブジェクトの再生状態を返します
    if not explosion_sound.get_num_channels() > 0 and start_time == float('inf'):
        print("効果音が完全に停止しました。")
        running = False # プログラムを終了

    pygame.time.delay(10)

pygame.quit()
print("プログラムが終了しました。")

fadeout() の注意点:

  • fadeout() が完了するまでプログラムは待機しません。非同期で処理が進むため、音が完全に停止したことを確認するには get_num_channels() などを利用する必要があります。
  • fadeout() を呼び出すと、その Sound オブジェクトが現在再生されているすべてのチャンネルに影響を与えます。

mixer.Sound.set_volume(value) を利用して音量を0にする

これは直接的な「停止」ではありませんが、音量をゼロに設定することで、実質的に音を聞こえなくすることができます。

  • 用途: 一時的に音を消したいが、後で同じ位置から再開する可能性がある場合や、fadeout() のように徐々に音量を下げたいが、時間を細かく制御したい場合に、自分でループ処理を組んで音量を徐々に減らすことができます。
  • 機能: Sound オブジェクトの再生音量を設定します。0.0 (ミュート) から 1.0 (最大音量) までの浮動小数点数です。

例 (音量を徐々に下げる手動フェードアウト)

import pygame
import time

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

screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Manual Fadeout Example")

try:
    alarm_sound = pygame.mixer.Sound("alarm.wav")
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    print("「alarm.wav」というファイルをこのスクリプトと同じディレクトリに置いてください。")
    pygame.quit()
    exit()

print("アラーム音を再生します。")
alarm_sound.play(-1) # -1 で無限ループ再生

running = True
fade_out_started = False
current_volume = 1.0
fade_duration = 2000 # 2秒かけてフェードアウト
fade_start_time = 0

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and not fade_out_started:
                print("スペースキーが押されました。手動フェードアウトを開始します。")
                fade_out_started = True
                fade_start_time = time.time()

    if fade_out_started:
        elapsed_time = (time.time() - fade_start_time) * 1000 # ミリ秒に変換
        
        if elapsed_time < fade_duration:
            # 音量を徐々に減らす
            current_volume = 1.0 - (elapsed_time / fade_duration)
            if current_volume < 0: # 念のため0以下にならないように
                current_volume = 0
            alarm_sound.set_volume(current_volume)
            # print(f"Current Volume: {current_volume:.2f}")
        else:
            # フェードアウト完了後、音を停止
            alarm_sound.stop()
            print("フェードアウトが完了し、音が停止しました。")
            running = False # プログラムを終了

    pygame.display.flip()
    pygame.time.delay(10)

pygame.quit()
print("プログラムが終了しました。")

set_volume() の注意点:

  • set_volume(0) は音を停止させるわけではなく、ただ音量をゼロにするだけです。Sound オブジェクト自体はまだ「再生中」の状態かもしれません(get_num_channels() は0より大きい値を返すことがあります)。リソースを完全に解放するには、最終的に stop() を呼び出すか、プログラムを終了させる必要があります。

pygame.mixer.Channel.stop() または pygame.mixer.Channel.fadeout()

mixer.Sound.stop()Sound オブジェクト全体に作用するのに対し、Channel オブジェクトの stop()fadeout() は、特定のチャンネルで再生されている音を停止します。これは、同じ Sound オブジェクトを複数の場所で同時に再生している場合に、個々の再生を制御したいときに非常に有用です。

  • 用途:
    • プレイヤーの攻撃音と敵の攻撃音が同時に再生されており、それぞれ独立して停止させたい場合。
    • 環境音(雨音など)を特定のチャンネルで再生し、ゲームの進行に応じてそのチャンネルだけを停止・フェードアウトさせたい場合。
  • 背景: Pygameのミキサーは、内部的に「チャンネル」という概念を持っています。Sound.play() を呼び出すと、Pygameは自動的に空いているチャンネルを見つけて、そこで音を再生します。


import pygame
import time

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

screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Channel Control Example")
font = pygame.font.Font(None, 28)

try:
    bg_loop_sound = pygame.mixer.Sound("background_loop.wav") # 長めのループ音
    one_shot_sound = pygame.mixer.Sound("one_shot.wav")     # 短い効果音
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    print("「background_loop.wav」と「one_shot.wav」を準備してください。")
    pygame.quit()
    exit()

# チャンネルを明示的に取得・管理
# チャンネル0 をBGM用、チャンネル1 を効果音用として使う
bg_channel = pygame.mixer.Channel(0)
fx_channel = pygame.mixer.Channel(1)

print("バックグラウンドサウンドをチャンネル0で再生します。")
bg_channel.play(bg_loop_sound, -1) # 無限ループ

running = True
message = "Press SPACE for One-Shot Sound, B to Stop BG Sound, Q to Quit."

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                print("ワンショットサウンドをチャンネル1で再生します。")
                fx_channel.play(one_shot_sound) # チャンネル1で再生
            
            elif event.key == pygame.K_b:
                if bg_channel.get_busy(): # チャンネルが使用中か確認
                    print("バックグラウンドサウンドをチャンネル0で停止します。")
                    bg_channel.stop() # チャンネル0の音を停止
                else:
                    print("バックグラウンドサウンドは停止中です。再開します。")
                    bg_channel.play(bg_loop_sound, -1) # 再開
            
            elif event.key == pygame.K_q:
                running = False

    # 画面描画
    screen.fill((0, 0, 0))
    text_surface = font.render(message, True, (255, 255, 255))
    screen.blit(text_surface, (20, 100))
    
    # チャンネルの現在の状態を表示
    bg_status = f"BG Channel (0): {'Playing' if bg_channel.get_busy() else 'Stopped'}"
    fx_status = f"FX Channel (1): {'Playing' if fx_channel.get_busy() else 'Stopped'}"
    screen.blit(font.render(bg_status, True, (0, 255, 0)), (20, 150))
    screen.blit(font.render(fx_status, True, (0, 255, 0)), (20, 180))

    pygame.display.flip()
    pygame.time.delay(10)

pygame.quit()
print("プログラムが終了しました。")

Channel オブジェクトの注意点:

  • pygame.mixer.set_num_channels(num) で、ミキサーが利用できるチャンネルの総数を設定できます。
  • pygame.mixer.find_channel() で空いているチャンネルを動的に取得することもできます。
  • pygame.mixer.Channel.stop() / fadeout(): 特定のチャンネルで再生されている音を停止・フェードアウトします。同じ Sound オブジェクトが複数の場所で再生されている場合に、個々の再生を細かく制御したい場合に強力です。
  • mixer.Sound.set_volume(0): 音量をゼロにするだけで、再生自体は続いている可能性があります。手動でフェードアウトを実装する際に利用できます。
  • mixer.Sound.fadeout(time): 滑らかに音量を下げてから停止。より自然な音の終了に適しています。
  • mixer.Sound.stop(): 最も基本的な即時停止。特定の Sound オブジェクトの再生をすべて停止します。

これらの代替方法は、Pygameでより柔軟かつ洗練されたオーディオ体験を実現するために非常に役立ちます。状況に応じて最適な方法を選択してください。 Pygame の mixer.Sound.stop() は、効果音を即座に停止する最も直接的な方法ですが、状況によっては代替となる、あるいは組み合わせることでより柔軟な制御が可能になるメソッドがあります。

Sound.fadeout(time): フェードアウトして停止

stop() は音を瞬時に停止しますが、fadeout() は指定した時間(ミリ秒)をかけて徐々に音量を下げ、その後停止します。これにより、 abrupt な音の途切れを防ぎ、より自然な音の停止を実現できます。

特徴

  • BGM (pygame.mixer.music) にも同様の fadeout() メソッドがあります。
  • stop() とは異なり、呼び出し後も指定時間の間は再生が続きます。
  • 指定された時間で音量が0になり、その後自動的に停止します。

使用例

import pygame
import time

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

screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Sound Fadeout Example")

try:
    bomb_sound = pygame.mixer.Sound("bomb.wav") # 例: 爆発音
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    pygame.quit()
    exit()

print("効果音を再生します。")
bomb_sound.play()

# 2秒後にフェードアウトを開始 (500ミリ秒かけて)
fade_start_time = time.time()
while time.time() - fade_start_time < 2:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    pygame.time.delay(10)

print("効果音を500ミリ秒かけてフェードアウトします...")
bomb_sound.fadeout(500) # 500ミリ秒かけてフェードアウト

# フェードアウトが完了するまで待つ (またはイベントループを継続)
fadeout_duration = 0.5 # 500ミリ秒 = 0.5秒
end_time = time.time() + fadeout_duration
while time.time() < end_time:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    pygame.time.delay(10)

print("効果音が停止しました。")
pygame.quit()

Sound.set_volume(value): 音量をゼロにする

stop() は再生を物理的に停止しますが、set_volume(0.0) を使用して音量をゼロに設定することで、音を「聞こえなくする」ことができます。これは、後で音量を元に戻して再生を再開したい場合に便利です。厳密には停止ではありませんが、ユーザー体験としては停止と同じ効果が得られます。

特徴

  • 後で set_volume(1.0) のように音量を元に戻せば、再生を再開できます。
  • 再生自体は継続しているため、メモリやCPUリソースは消費し続けます。
  • 音量を即座に設定します。

使用例

import pygame
import time

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

screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Sound Volume Control Example")

try:
    ambient_sound = pygame.mixer.Sound("ambient.wav") # 例: 環境音、ループ再生を想定
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    pygame.quit()
    exit()

ambient_sound.set_volume(0.5) # 初期音量
ambient_sound.play(-1) # ループ再生

print("環境音を再生中 (音量 0.5)。")

# 2秒後に音量をゼロにする
start_time = time.time()
while time.time() - start_time < 2:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    pygame.time.delay(10)

print("音量を0.0にします (実質的に停止)。")
ambient_sound.set_volume(0.0) # 音量をゼロに設定

# さらに2秒待つ (音は聞こえないが再生は継続している)
time.sleep(2)

print("音量を0.8に戻します (再生再開)。")
ambient_sound.set_volume(0.8) # 音量を戻す

# さらに2秒待つ
time.sleep(2)

print("最終的にsound.stop()で完全に停止します。")
ambient_sound.stop() # 完全に停止

pygame.quit()

pygame.mixer.Channel オブジェクトを使った停止

pygame.mixer.Sound.play() メソッドは、再生を開始した Channel オブジェクトを返すことがあります。この Channel オブジェクトを保持しておけば、その特定のチャンネルで再生されている音を個別に制御できます。Channel オブジェクトにも stop(), fadeout(), set_volume() メソッドがあります。

これは、同じ Sound オブジェクトを同時に複数回再生する場合(例: 銃声が連続して鳴る場合など)に特に強力な方法です。

特徴

  • find_channel() を使って空いているチャンネルを見つけ、そこに音を割り当てることができます。
  • sound.stop() はその Sound オブジェクトが再生されている 全ての チャンネルを停止しようとしますが、channel.stop() はその特定のチャンネルのみを停止します。
  • 個別の制御: 特定のチャンネルで再生されている音だけを停止できます。

使用例

import pygame
import time

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

screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Channel Control Example")
font = pygame.font.Font(None, 36)

try:
    laser_sound = pygame.mixer.Sound("laser.wav") # 例: レーザー音
    explosion_sound = pygame.mixer.Sound("explosion.wav") # 例: 爆発音
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    pygame.quit()
    exit()

# 各サウンドが再生されるチャンネルを保持するリスト
active_laser_channels = []
active_explosion_channels = []

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                # スペースキーでレーザー音を再生
                print("Laser sound played.")
                channel = laser_sound.play() # play()はChannelオブジェクトを返す
                if channel: # チャンネルが利用可能だった場合
                    active_laser_channels.append(channel)
            
            elif event.key == pygame.K_e:
                # Eキーで爆発音を再生
                print("Explosion sound played.")
                channel = explosion_sound.play()
                if channel:
                    active_explosion_channels.append(channel)
            
            elif event.key == pygame.K_s:
                # Sキーで全てのレーザー音を停止
                print("Stopping all laser sounds...")
                laser_sound.stop() # Soundオブジェクトに紐づく全ての再生を停止
                active_laser_channels = [] # リストもクリア
            
            elif event.key == pygame.K_x:
                # Xキーで最後に再生された爆発音を停止 (個別のチャンネル制御の例)
                if active_explosion_channels:
                    last_explosion_channel = active_explosion_channels.pop(0) # 古いものから停止
                    print(f"Stopping a specific explosion sound on channel {last_explosion_channel.get_id()}...")
                    last_explosion_channel.stop() # 特定のチャンネルの音を停止

    # 画面描画
    screen.fill((0, 0, 0))
    text_surface = font.render("SPACE: Laser, E: Explosion, S: Stop All Lasers, X: Stop One Explosion", True, (255, 255, 255))
    screen.blit(text_surface, text_surface.get_rect(center=(300, 200)))
    pygame.display.flip()

    # 短い遅延
    pygame.time.delay(10)

pygame.quit()

Channelオブジェクトの追加のメソッド(停止関連)

  • channel.get_busy(): そのチャンネルが現在何かを再生しているか(忙しいか)どうかを返します。
  • channel.unpause(): 一時停止した再生を再開します。
  • channel.pause(): そのチャンネルの再生を一時停止します。

これは mixer.Sound.stop() ではありませんが、全ての効果音(とBGM)を一度に停止したい場合に非常に便利です。

特徴

  • 緊急停止や、ゲームオーバーなどで全ての音をリセットしたい場合に適しています。
  • ミキサーが管理する全てのチャンネルで再生されている音を停止します。
import pygame
import time

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

screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Global Stop Example")

try:
    sound1 = pygame.mixer.Sound("sound1.wav")
    sound2 = pygame.mixer.Sound("sound2.wav")
except pygame.error as e:
    print(f"効果音ファイルの読み込みエラー: {e}")
    pygame.quit()
    exit()

print("複数の効果音を再生します。")
sound1.play(-1) # ループ再生
sound2.play()

# 3秒後に全ての音を停止
start_time = time.time()
while time.time() - start_time < 3:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    pygame.time.delay(10)

print("pygame.mixer.stop()で全ての音を停止します。")
pygame.mixer.stop() # 全てのSoundとMusicの再生を停止

# さらに2秒待つ (何も聞こえないはず)
time.sleep(2)

print("プログラムが終了しました。")
pygame.quit()