programing

Python에서 *.wav 파일 읽기

codeshow 2023. 9. 14. 23:43
반응형

Python에서 *.wav 파일 읽기

.wav 파일로 작성된 사운드를 분석해야 합니다.이를 위해 이 파일을 숫자 집합(예: 배열)으로 변환해야 합니다.웨이브 패키지를 사용해야 할 것 같습니다.하지만 정확히 어떻게 작동하는지는 모르겠습니다.예를 들어 다음과 같이 했습니다.

import wave
w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r')
for i in range(w.getnframes()):
    frame = w.readframes(i)
    print frame

이 코드의 결과로 음압을 시간의 함수로 볼 수 있을 것이라 예상했습니다.이와는 대조적으로 이상하고 신비로운 기호들이 많이 보입니다. (16진수가 아닌)아무도, 제발 도와줄 수 있습니까?

문서에 의하면,scipy.io.wavfile.read(somefile)두 가지 항목으로 구성된 튜플을 반환합니다. 첫 번째 항목은 초당 샘플의 샘플링 속도이고, 두 번째 항목은 a입니다.numpy파일에서 읽은 모든 데이터가 포함된 배열:

from scipy.io import wavfile
samplerate, data = wavfile.read('./output/audio.wav')

모듈을 사용하여 -32768과 32767 사이의 2의 상보 이진에 있는 파형 프레임을 취할 수 있습니다(즉, -32768과 -32767 사이).0x8000그리고.0x7FFFMONO, 16-BIT, WAVE 파일을 읽습니다.는 이 웹페이지가 이 내용을 구성하는 데 꽤 유용하다고 생각했습니다.

import wave, struct

wavefile = wave.open('sine.wav', 'r')

length = wavefile.getnframes()
for i in range(0, length):
    wavedata = wavefile.readframes(1)
    data = struct.unpack("<h", wavedata)
    print(int(data[0]))

이 토막글은 한 프레임을 읽습니다.두 개 이상의 프레임(예: 13)을 읽으려면 다음을 사용합니다.

wavedata = wavefile.readframes(13)
data = struct.unpack("<13h", wavedata)

wav를 읽을 수 있는 다양한 파이썬 모듈:

웨이브 오디오 파일을 읽을 수 있는 라이브러리는 적어도 다음과 같습니다.

가장 간단한 예:

SoundFile의 간단한 예는 다음과 같습니다.

import soundfile as sf
data, samplerate = sf.read('existing_file.wav') 

출력 형식:

경고: 데이터가 항상 라이브러리에 따라 동일한 형식이 아닙니다.예를 들어 다음과 같습니다.

from scikits import audiolab
from scipy.io import wavfile
from sys import argv
for filepath in argv[1:]:
    x, fs, nb_bits = audiolab.wavread(filepath)
    print('Reading with scikits.audiolab.wavread:', x)
    fs, x = wavfile.read(filepath)
    print('Reading with scipy.io.wavfile.read:', x)

출력:

Reading with scikits.audiolab.wavread: [ 0.          0.          0.         ..., -0.00097656 -0.00079346 -0.00097656]
Reading with scipy.io.wavfile.read: [  0   0   0 ..., -32 -26 -32]

SoundFile 및 Audiolab 리턴은 -1과 1 사이에서 플로팅됩니다(마탭이 하는 것처럼 오디오 신호에 대한 규칙).Scipy 및 wave는 정수를 반환합니다. 이 정수는 인코딩 비트 수에 따라 Float로 변환할 수 있습니다. 예를 들어 다음과 같습니다.

from scipy.io.wavfile import read as wavread
samplerate, x = wavread(audiofilename)  # x is a numpy array of integers, representing the samples 
# scale to -1.0 -- 1.0
if x.dtype == 'int16':
    nb_bits = 16  # -> 16-bit wav files
elif x.dtype == 'int32':
    nb_bits = 32  # -> 32-bit wav files
max_nb_bit = float(2 ** (nb_bits - 1))
samples = x / (max_nb_bit + 1)  # samples is a numpy array of floats representing the samples 

IMHO, 사운드 파일에서 NumPy 배열로 오디오 데이터를 가져오는 가장 쉬운 방법은 SoundFile입니다.

import soundfile as sf
data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')

또한 24비트 파일을 즉시 사용할 수 있습니다.

사용 가능한 사운드 파일 라이브러리가 많습니다. 몇 가지 장단점을 볼 수 있는 개요를 작성했습니다.또한 모듈로 24비트 wav 파일을 읽는 방법을 설명하는 페이지도 제공합니다.

당신은 그 곡예들을 사용해서 이것을 해낼 수 있습니다.오디오 실험실 모듈이것은 NumPy와 SciPy 기능을 하기 위해서 필요하고 libsnd 파일도 필요합니다.

참고로 저는 OSX가 아닌 Ubunutu에서만 작동할 수 있었습니다.

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

이제 웨이브 데이터가 있습니다.

블록 단위로 오디오 블록을 처리하려면 전체 오디오를 메모리에 로드하면 캐시 미스가 많이 발생하고 프로그램 속도가 느려진다는 점에서 주어진 해결책 중 일부는 매우 좋지 않습니다.python-wave 파일은 생성기를 통해 효율적이고 투명한 블록 관리를 사용하여 NumPy 블록 단위로 처리할 수 있는 일부 pythonic 구조체를 제공합니다.다른 pythonic nice는 파일의 컨텍스트 관리자, 메타데이터는 속성...빠른 프로토타입을 개발하고 효율성을 고려하지 않기 때문에 전체 파일 인터페이스를 원할 경우 전체 파일 인터페이스는 그대로 유지됩니다.

간단한 처리 예는 다음과 같습니다.

import sys
from wavefile import WaveReader, WaveWriter

with WaveReader(sys.argv[1]) as r :
    with WaveWriter(
            'output.wav',
            channels=r.channels,
            samplerate=r.samplerate,
            ) as w :

        # Just to set the metadata
        w.metadata.title = r.metadata.title + " II"
        w.metadata.artist = r.metadata.artist

        # This is the prodessing loop
        for data in r.read_iter(size=512) :
            data[1] *= .8     # lower volume on the second channel
            w.write(data)

이 예제에서는 일반적으로 필요한 크기보다 작은 마지막 블록의 경우에도 동일한 블록을 재사용하여 전체 파일을 읽습니다.이 경우 블록의 한 조각을 얻을 수 있습니다.따라서 이후의 처리를 위해 하드코딩된 512 크기를 사용하는 대신 반환된 블록 길이를 신뢰해야 합니다.

파형 데이터를 전송하려면 SciPy를 사용해야 합니다.

여기에 내장된 웨이브 모듈[1]을 사용하는 파이썬 3 솔루션이 있습니다. n개의 채널과 8,16,24...비트에서 작동합니다.

import sys
import wave

def read_wav(path):
    with wave.open(path, "rb") as wav:
        nchannels, sampwidth, framerate, nframes, _, _ = wav.getparams()
        print(wav.getparams(), "\nBits per sample =", sampwidth * 8)

        signed = sampwidth > 1  # 8 bit wavs are unsigned
        byteorder = sys.byteorder  # wave module uses sys.byteorder for bytes

        values = []  # e.g. for stereo, values[i] = [left_val, right_val]
        for _ in range(nframes):
            frame = wav.readframes(1)  # read next frame
            channel_vals = []  # mono has 1 channel, stereo 2, etc.
            for channel in range(nchannels):
                as_bytes = frame[channel * sampwidth: (channel + 1) * sampwidth]
                as_int = int.from_bytes(as_bytes, byteorder, signed=signed)
                channel_vals.append(as_int)
            values.append(channel_vals)

    return values, framerate

결과를 NumPy 배열로 변경할 수 있습니다.

import numpy as np

data, rate = read_wav(path)
data = np.array(data)

참고로, 빠른 것보다는 읽을 수 있게 하려고 노력했습니다.한 번에 모든 데이터를 읽는 속도가 거의 2배나 빠르다는 것을 발견했습니다.예.

with wave.open(path, "rb") as wav:
    nchannels, sampwidth, framerate, nframes, _, _ = wav.getparams()
    all_bytes = wav.readframes(-1)

framewidth = sampwidth * nchannels
frames = (all_bytes[i * framewidth: (i + 1) * framewidth]
            for i in range(nframes))

for frame in frames:
    ...

파이썬 사운드 파일이 약 2배 더 빠르지만(순수한 CPython으로는 이 속도에 접근하기 어렵습니다).

[1] https://docs.python.org/3/library/wave.html

당신이 무엇을 찾고 있는지 아는 한, 당신은 DSP(Digital Signal Processing)라는 이론 분야에 진출하고 있습니다.이 엔지니어링 영역은 이산 시간 신호를 복잡한 적응 필터로 단순하게 분석하는 데서 비롯됩니다.좋은 아이디어는 이산 시간 신호를 벡터로 생각하는 것입니다. 여기서 벡터의 각 요소는 원래의 연속 시간 신호의 샘플링 값입니다.샘플을 벡터 형태로 얻으면 이 벡터에 다양한 디지털 신호 기법을 적용할 수 있습니다.

안타깝게도 파이썬에서는 오디오 파일에서 NumPy 배열 벡터로 이동하는 것이 다소 번거롭습니다.한 프로그래밍 언어를 다른 프로그래밍 언어보다 우상화하지 않는다면 매트랩/옥타브를 사용해보는 것을 강력히 추천합니다.Matlab은 파일에서 샘플에 바로 접근할 수 있게 해줍니다.audioread()합니다. :) DSP를 설계된 . 이것은 다음과 같습니다. :)를 DSP해히된은다가고을다이다가은s된s히해고dskduo이)ea을합니다 .

그럼에도 불구하고, 정말로 파이썬에 들어갈 생각이 있으시다면, 단계별로 안내해 드리겠습니다.


1. 샘플 가져오기

가장 쉽게 샘플을 얻을 수 있는 방법은.wav파일:

from scipy.io import wavfile

sampling_rate, samples = wavfile.read(f'/path/to/file.wav')


, 은 할 을 할 을 사용할 수 있습니다.wave그리고.struct샘플을 가져올 패키지:

import numpy as np
import wave, struct

wav_file = wave.open(f'/path/to/file.wav', 'rb')
# from .wav file to binary data in hexadecimal
binary_data = wav_file.readframes(wav_file.getnframes())
# from binary file to samples
s = np.array(struct.unpack('{n}h'.format(n=wav_file.getnframes()*wav_file.getnchannels()), binary_data))

대한 : 에 :binary_data는 ㅇbytes사람이 이해할 수 있는 것이 아니고 기계에만 의미를 부여할 수 있는 물체입니다.문을성할수다다수gst할u이en성문을 stype(binary_data). 이 괴상한 캐릭터들에 대해 좀 더 이해하고 싶다면, 여기를 클릭하세요.

인 경우의 채널이 있는 ), 이하여 가 를 하여 과 으로 이 으로 가 과 scipy.io

s_like_scipy = s.reshape(-1, wav_file.getnchannels())

각 열은 하나의 채널입니다.쪽이든,,e에서 얻은 .wav파일은 신호의 시간적 행동을 플롯하고 이해하는 데 사용될 수 있습니다.

두 대안 모두에서 파일에서 얻은 샘플은 LPCM(Linear Pulse Code Modulation)에 표시됩니다.


2. 오디오 샘플에 디지털 신호 처리 작업을 수행합니다.

그 부분은 고객님께 맡기겠습니다 :) 하지만 DSP를 통해 안내해 드릴 수 있는 좋은 책입니다.안타깝게도, 나는 파이썬으로 된 좋은 책을 알지 못합니다. 대개 끔찍한 책들입니다.그러나 걱정하지 마십시오. 이론은 그 언어를 도메인화하는 한 어떤 프로그래밍 언어를 사용하더라도 동일한 방식으로 적용될 수 있습니다.

어떤 책을 주든지 고전적인 작가들, 예를 들어 프로아키스나 오펜하임 같은...그들이 사용하는 언어 프로그래밍에 신경쓰지 마세요.Python을 사용하는 오디오의 DPS에 대한 보다 실용적인 가이드는 이 페이지를 참조하십시오.

3. 필터링된 오디오 샘플 재생

import pyaudio

p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(wav_file.getsampwidth()),
                channels = wav_file.getnchannels(),
                rate = wav_file.getframerate(),
                output = True)
# from samples to the new binary file
new_binary_data = struct.pack('{}h'.format(len(s)), *s)
stream.write(new_binary_data)

wav_file.getsampwidth(),는당트며,,wav_file.getframerate()는 샘플링 속도입니다.입력 오디오의 파라미터만 동일하게 사용하면 됩니다.


새합니다. 를 으로 으로 .wav을 대다

wav_file=wave.open('/phat/to/new_file.wav', 'w')

wav_file.setparams((nchannels, sampwidth, sampling_rate, nframes, "NONE", "not compressed"))

for sample in s:
   wav_file.writeframes(struct.pack('h', int(sample)))

nchannels채널의 수,의입니다 입니다.sampwidth,트다당다입니다.sampling_rate 속도, λ입니다 입니다.nframes총 표본 수 입니다.

1채널 24비트 WAV 파일을 읽어야 했습니다.Nak이 올린 위의 글은 매우 유용했습니다.그러나 basj 24-bit가 위에서 언급한 것처럼 간단하지 않습니다.나는 마침내 다음의 토막글을 사용하여 그것을 작동시켰습니다.

from scipy.io import wavfile
TheFile = 'example24bit1channelFile.wav'
[fs, x] = wavfile.read(TheFile)

# convert the loaded data into a 24bit signal

nx = len(x)
ny = nx/3*4    # four 3-byte samples are contained in three int32 words

y = np.zeros((ny,), dtype=np.int32)    # initialise array

# build the data left aligned in order to keep the sign bit operational.
# result will be factor 256 too high

y[0:ny:4] = ((x[0:nx:3] & 0x000000FF) << 8) | \
  ((x[0:nx:3] & 0x0000FF00) << 8) | ((x[0:nx:3] & 0x00FF0000) << 8)
y[1:ny:4] = ((x[0:nx:3] & 0xFF000000) >> 16) | \
  ((x[1:nx:3] & 0x000000FF) << 16) | ((x[1:nx:3] & 0x0000FF00) << 16)
y[2:ny:4] = ((x[1:nx:3] & 0x00FF0000) >> 8) | \
  ((x[1:nx:3] & 0xFF000000) >> 8) | ((x[2:nx:3] & 0x000000FF) << 24)
y[3:ny:4] = (x[2:nx:3] & 0x0000FF00) | \
  (x[2:nx:3] & 0x00FF0000) | (x[2:nx:3] & 0xFF000000)

y = y/256   # correct for building 24 bit data left aligned in 32bit words

-1에서 +1 사이의 결과가 필요한 경우 추가 스케일링이 필요합니다.아마 거기 계신 분들 중에 이게 유용하다고 생각하시는 분들도 계실 겁니다.

두 개의 파일만 있고 샘플율이 상당히 높다면 그냥 둘 수 있습니다.

from scipy.io import wavfile
rate1,dat1 = wavfile.read(File1)
rate2,dat2 = wavfile.read(File2)

if len(dat2) > len(dat1):#swap shortest
    temp = dat2
    dat2 = dat1
    dat1 = temp

output = dat1
for i in range(len(dat2)/2): output[i*2]=dat2[i*2]

wavfile.write(OUTPUT,rate,dat)

PyDub(http://pydub.com/) 은 언급되지 않았으며 이는 수정되어야 합니다.IMO 이 라이브러리는 현재 파이썬에서 오디오 파일을 읽을 수 있는 가장 포괄적인 라이브러리입니다. 비록 오류가 없는 것은 아니지만 말입니다.wav 파일 읽기:

from pydub import AudioSegment

audio_file = AudioSegment.from_wav('path_to.wav')
# or
audio_file = AudioSegment.from_file('path_to.wav')

# do whatever you want with the audio, change bitrate, export, convert, read info, etc.
# Check out the API docs http://pydub.com/

PS. 예는 wav 파일을 읽는 것이지만, PyDub은 다양한 형식을 즉시 처리할 수 있습니다.주의할 점은 기본 Python wav 지원과 fmpeg를 모두 기반으로 하기 때문에 fmpeg를 설치해야 하고 많은 pydub 기능이 fmpeg 버전에 의존한다는 것입니다.보통 fmpeg가 할 수 있다면, pydub도 할 수 있습니다(상당히 강력합니다).

비신고자:저는 프로젝트와 관련은 없지만, 헤비 유저입니다.

다른 답변들이 제시되면서 파이썬으로 wav 파일을 읽을 수 있는 많은 방법들이 있습니다.능용용 wave모듈은 외부 의존성이 필요 없다는 장점이 있습니다. 번째 – 또는 첫 채널의 합니다. 첫 번째 채널은째션는노다오브을플고첫의째를첫를다플0의te째f첫––ne째se션s:d첫sav

import wave
import sys

w = wave.open('/path/to/your-file.wav', 'rb')
channels = w.getnchannels()
samplewidth = w.getsampwidth()
print(f"Audio has {channels} channels and each sample is {samplewidth} bytes ({samplewidth * 8} bits) wide")
samples = []

# Iterate over the frames
for n in range(w.getnframes()):
    # Read a frames bytes
    frame = w.readframes(n)
    # Skip empty frames
    if frame != b'':
        # Convert the frame into a list of integers, assuming the systems
        # endianess and signed integers
        frame_data = [int.from_bytes(frame[i:i+samplewidth], byteorder=sys.byteorder, signed=True) for i in range(0, len(frame), samplewidth)]
        # If we have more than one channel the samples of each channel
        # should be interleaved
        if channels == 1:
            # Mono is simple: each frame can contain multiple samples
            for sample in frame_data:
                samples.append(sample)
        elif channels == 2:
            # Stereo samples are interleaved: (L/R/L/R/...)
            # Iterate in steps of 2 over the frames and deinterleave
            # them into the samples for left and right
            for c in range(0, len(frame_data), 2):
                left, right = zip(frame_data[c:c+2])
                left, right = left[0], right[0]
                samples.append(right)
        else:
            # Print lame excuse and exit
            print(f"Error: Sorry, we do not support wave files with {channels} channels", file=sys.stderr)
            exit(1)

# Print first 100 samples
print(samples[100:])

세부 사항

샘플

궁극적으로 이진 파일의 모든 것은 바이트(이상한 문자)입니다.,로 8비트며음중일다수는다수ea일rt며중음는snfs0아니면1 파일에 이 다른비트 을 알 수 . 이제 오디오 파일에 대한 약간의 지식으로 wav 파일이 다른 비트 심도로 제공된다는 것을 알 수 있습니다. CD, 등은이며, 에게 16비트의 합니다.2^16아니면65536단계들. 그러나 사운드 스튜디오 응용 프로그램을 위한 24비트 또는 그 이상의 32비트(float) 파일도 있습니다.는 샘플의 를 알아야 것을 즉,의를로기는의에다는의와야를른다야와를의t는에즉s,의wynonefweytsrede를e,의.getsampwidth() 입니다 에게 입니다

예를 들어 24비트 wav 파일을 읽었더니 샘플 너비가 3바이트였는데 실제로 24비트에서 3×8비트 결과가 나왔습니다.따라서 프레임에서 3바이트를 가져와 정수로 변환해야 합니다.

sample = [int.from_bytes(frame[i:i+samplewidth], byteorder=sys.byteorder, signed=True) for i in range(0, len(frame), samplewidth)]

byteorder=sys.byteorder는 바이트의 종성을 설명합니다. 따라서 숫자를 구성하기 위해 왼쪽에서 오른쪽으로 읽을 필요가 있는지, 오른쪽에서 왼쪽으로 읽을 필요가 있는지("큰"), 오른쪽에서 왼쪽으로 읽거나("작은").이 경우 우리는 우리 시스템의 궁극성이 무엇이든 취할 수 있습니다.8비트 오디오의 경우 바이트가 하나밖에 없고 읽을 수 있는 방향이 없으므로 무시할 수 있습니다.

signed=True양의 부호만 있는 비부호 정수와는 반대로 부호가 있는 정수가 예상된다고 합니다.대부분의 일반적인 16비트 및 24비트 오디오 파일에 대해 서명이 가능합니다.

들어,0과 + 사이의 플로트(float)로계산해야 합니다(예: -1.0 +1.0 에서 +1.0 해야 으로 의 를 의 의 로 를 ( -1.0 +1.0 ).2**24 // 2샘플을 그것으로 나눕니다.

채널

웨이브 파일은 둘 이상의 오디오 채널을 전송할 수 있습니다.모노, 스테레오, 서라운드 또는 기타 다채널 구성일 수 있습니다.모노는 단순한 경우이지만 다채널 웨이브의 경우 샘플은 일반적으로 인터리브됩니다.즉, 하나의 프레임이 교대로 모든 채널에서 샘플을 운반한다는 것을 의미합니다.스테레오를 가정하면 다음과 같습니다.

L/R/L/R/L/R

나는 버마왕뱀을 사용합니다.zip하여 포장하는 을 합니다.left그리고.right변수들.

주의사항

웨이브 파일을 읽는 데 있어 가장 큰 어려움은 웨이브 파일이 볼 수 있는 모든 가능한 방법을 다루는 것이라고 생각합니다.파형 파일은 그보다 훨씬 더 복잡해질 수 있습니다(예: 메타 데이터 헤더, 챕터 표시 등). 따라서 완벽한 호환성을 위해서는 다른 것을 사용하는 것이 현명할 수 있습니다.하지만 이런 것을 읽고 싶은 웨이브 파일이 잘 작동할 수도 있다는 것을 알고 있다면요.

도 합니다 할 수 있습니다.import wavio도서관 또한 소리에 대한 기본적인 지식이 필요합니다.

언급URL : https://stackoverflow.com/questions/2060628/reading-wav-files-in-python

반응형