音声処理技術実装メモ

1. PCMファイルの直接再生

RAW PCMデータを直接再生するには以下のコマンドを使用します:

#!/bin/bash
play -t raw -r 44100 -e signed -b 16 -c 2 audio_data.pcm
play -t raw -r 48000 -e float -b 32 -c 2 ./decoded/output.pcm

2. 開発ライブラリのインストールと設定

必要な開発ライブラリをインストールします:

sudo apt install libjsoncpp-dev
sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json

sudo apt install libcurl4-openssl-dev
sudo ln -s /usr/include/x86_64-linux-gnu/curl /usr/include/curl

sudo apt install libopencv-dev

3. CMakeを用いたFFmpegプロジェクト設定

cmake_minimum_required(VERSION 3.10)

project(media_player)

set(SOURCE_FILES main.cpp)
include_directories("/usr/include/x86_64-linux-gnu")
link_directories("/usr/lib/x86_64-linux-gnu")

add_executable(media_player ${SOURCE_FILES})

target_link_libraries(media_player avutil avcodec avformat swresample)

4. 音声形式変換処理

PCMからWAVへの変換実装:

def convert_pcm_to_wav(input_path, output_path, sample_rate, channels, bit_depth):
    with open(input_path, "rb") as pcm_file:
        raw_data = pcm_file.read()
    
    with wave.open(output_path, "wb") as wav_file:
        wav_file.setnchannels(channels)
        wav_file.setsampwidth(bit_depth // 8)
        wav_file.setframerate(sample_rate)
        wav_file.writeframes(raw_data)

5. 多チャンネル音声からの単一チャンネル抽出

import numpy as np

def extract_single_channel(multi_channel_data, total_channels, target_channel):
    reshaped_data = multi_channel_data.reshape(-1, total_channels)
    transposed_data = reshaped_data.T
    return transposed_data[target_channel]

def extract_channel_from_file(input_file, channels, channel_index, bit_resolution, output_file):
    dtype_map = {16: np.int16, 32: np.int32}
    audio_data = np.fromfile(input_file, dtype=dtype_map[bit_resolution])
    mono_data = extract_single_channel(audio_data, channels, channel_index)
    mono_data.tofile(output_file)

6. ALSAオーディオデバイスの設定と制御

import alsaaudio

def initialize_playback_device(device_name, sample_rate=16000, channels=8):
    try:
        audio_device = alsaaudio.PCM(
            type=alsaaudio.PCM_PLAYBACK,
            mode=alsaaudio.PCM_NORMAL,
            rate=sample_rate,
            channels=channels,
            format=alsaaudio.PCM_FORMAT_S16_LE,
            periodsize=160,
            device=f"plughw:{device_name}"
        )
        return audio_device
    except Exception as error:
        print(f"ALSA device initialization failed: {error}")
        return None

7. WAVファイル再生スレッド実装

import wave
import threading

class AudioPlayer:
    def __init__(self):
        self.audio_device = None
        self.playback_active = False
    
    def play_wav_file(self, file_path, device_name):
        def playback_thread():
            with wave.open(file_path, 'rb') as audio_file:
                frame_rate = audio_file.getframerate()
                num_channels = audio_file.getnchannels()
                sample_width = audio_file.getsampwidth()
                
                self.audio_device = initialize_playback_device(
                    device_name, frame_rate, num_channels
                )
                
                if not self.audio_device:
                    return
                
                frame_size = frame_rate // 100
                audio_data = audio_file.readframes(frame_size)
                
                while audio_data and self.playback_active:
                    try:
                        self.audio_device.write(audio_data)
                    except alsaaudio.ALSAAudioError as e:
                        print(f"Playback error: {e}")
                        break
                    audio_data = audio_file.readframes(frame_size)
                
                if self.audio_device:
                    self.audio_device.close()
        
        self.playback_active = True
        thread = threading.Thread(target=playback_thread)
        thread.start()

8. サブプロセスによる音声再生制御

import subprocess
import time

def play_audio_with_timeout(audio_file, device_spec, timeout_seconds):
    env = os.environ.copy()
    env['AUDIODEV'] = device_spec
    
    process = subprocess.Popen(
        f"play {audio_file}", 
        shell=True, 
        env=env
    )
    
    time.sleep(timeout_seconds)
    process.terminate()
    process.wait()
    
    # 端末設定の復元
    subprocess.run("stty sane", shell=True)

9. ファイルシステム操作ユーティリティ

import os

def find_directory(base_path, target_dir):
    for root, dirs, files in os.walk(base_path):
        if target_dir in dirs:
            return os.path.join(root, target_dir)
    return None

def locate_file(base_path, filename):
    for root, dirs, files in os.walk(base_path):
        if filename in files:
            return os.path.join(root, filename)
    return None

10. 依存関係解析

def analyze_dependencies(project_path):
    command = f'grep -r "import" {project_path}'
    process = os.popen(command)
    output_lines = process.readlines()
    process.close()
    
    dependencies = set()
    
    for line in output_lines:
        if line.strip().startswith('#'):
            continue
            
        content = line.split(':', 1)[1].strip()
        
        if 'from' not in content:
            imports = content.replace('import', '').strip().split(',')
            dependencies.update(imp.strip() for imp in imports)
        else:
            module = content.split('from')[1].split('import')[0].strip()
            dependencies.add(module)
    
    return dependencies

タグ: ALSA FFmpeg PCM WAV 音声処理

8月7日 12:31 投稿