【问题标题】:How to manipulate wav file data in Python?如何在 Python 中操作 wav 文件数据?
【发布时间】:2013-09-05 19:13:57
【问题描述】:

我正在尝试读取一个 wav 文件,然后逐个采样地操作其内容

这是我目前所拥有的:

import scipy.io.wavfile
import math

rate, data = scipy.io.wavfile.read('xenencounter_23.wav')

for i in range(len(data)):
    data[i][0] = math.sin(data[i][0])
    print data[i][0]

我得到的结果是:

0
0
0
0
0
0

它正在正确读取,因为如果我写 print data[i],我通常会得到大小为 2 的非零数组。

【问题讨论】:

    标签: python scipy wav


    【解决方案1】:

    wavfile.read 返回的数组data 是一个 integer 数据类型的 numpy 数组。 numpy数组的数据类型不能原地改变,所以这一行:

    data[i][0] = math.sin(data[i][0])
    

    math.sin 的结果转换为一个整数,该整数始终为0。

    创建一个新的浮点数组来代替该行来存储您的计算结果。

    或者使用numpy.sin一次计算数组中所有元素的正弦值:

    import numpy as np
    import scipy.io.wavfile
    
    rate, data = scipy.io.wavfile.read('xenencounter_23.wav')
    
    sin_data = np.sin(data)
    
    print sin_data
    

    从您的其他 cmets 看来,您希望获取每个值的正弦并将结果写为新的 wav 文件。

    这是一个(我认为)做你想做的事的例子。我将从这里使用文件“M1F1-int16-AFsp.wav”:http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html。函数show_info 只是一个方便的方式来说明每一步的结果。如果您使用的是交互式 shell,则可以使用它来检查变量及其属性。

    import numpy as np
    from scipy.io import wavfile
    
    def show_info(aname, a):
        print "Array", aname
        print "shape:", a.shape
        print "dtype:", a.dtype
        print "min, max:", a.min(), a.max()
        print
    
    rate, data = wavfile.read('M1F1-int16-AFsp.wav')
    
    show_info("data", data)
    
    # Take the sine of each element in `data`.
    # The np.sin function is "vectorized", so there is no need
    # for a Python loop here.
    sindata = np.sin(data)
    
    show_info("sindata", sindata)
    
    # Scale up the values to 16 bit integer range and round
    # the value.
    scaled = np.round(32767*sindata)
    
    show_info("scaled", scaled)
    
    # Cast `scaled` to an array with a 16 bit signed integer data type.
    newdata = scaled.astype(np.int16)
    
    show_info("newdata", newdata)
    
    # Write the data to 'newname.wav'
    wavfile.write('newname.wav', rate, newdata)
    

    这是输出。 (最初的警告意味着文件中可能存在scipy.io.wavfile.read 无法理解的一些元数据。)

    <snip>/scipy/io/wavfile.py:147: WavFileWarning: Chunk (non-data) not understood, skipping it.
      WavFileWarning)
    Array 'data'
    shape: (23493, 2)
    dtype: int16
    min, max: -7125 14325
    
    Array 'sindata'
    shape: (23493, 2)
    dtype: float32
    min, max: -0.999992 0.999991
    
    Array 'scaled'
    shape: (23493, 2)
    dtype: float32
    min, max: -32767.0 32767.0
    
    Array 'newdata'
    shape: (23493, 2)
    dtype: int16
    min, max: -32767 32767
    

    新文件“newname.wav”包含两个带符号的 16 位值通道。

    【讨论】:

    • +1 建议np.sin(...)。这绝对是要走的路,而且会方式更快。
    • 谢谢。我尝试将正弦值保存到另一个数组(或从技术上讲是一个列表),但是在写入时我收到错误 AttributeError: 'list' object has no attribute 'ndim'
    • @Jamil,我想你会想要熟悉 numpy 数组的基础知识(例如engr.ucsb.edu/~shell/che210d/numpy.pdf,或wiki.scipy.org/Tentative_NumPy_Tutorial,或其他许多 numpy 教程)。没有看到你做了什么,我无法解决这个问题。
    • 我只是在看他们。我想我需要将列表转换为 numpy 数组。我所做的是:for i in range(len(data)): data2.append([math.sin(data[i][0]), math.sin(data[i][1])]) 带有一个初始化列表 data2,然后我写了scipy.io.wavfile.write('newname.wav',rate,data2)rate 是读取原始文件的原始速率
    • @Jamil:我已经更新了我的答案。请注意,我的代码中有 no python 循环。所有 numpy 操作都是矢量化的。如果您完成其中一个 numpy 教程,您将了解更多相关信息。
    猜你喜欢
    • 1970-01-01
    • 2013-07-13
    • 2022-10-15
    • 1970-01-01
    相关资源
    最近更新 更多