2012-01-08 21 views
2

私は多かれ少なかれPythonの初心者で、このevolutionary Mona Lisaの実験のオーディオに取り組んでいます。 numpyの配列に与えられた.wavファイルを読む数値が「シャッフルされた」NumPy配列

  1. 以下のコードはに意図されます。

  2. 波形の 'ゼロクロス'を検出します。つまり、配列要素が符号を変更したときです。これらのポイントで、アレイを波形の「チャンク」のネストされたリストに分割します。
  3. 正のチャンクを分離してから、これらのチャンクをシャッフルし、それらをNumPyアレイに再結合します。リストには2000以上の要素があるので、random.shuffle()は使用できません。
  4. シャッフルされた配列 の 'fitness'を、シャッフルされた配列と元のサンプルの差の2乗として定義された元のサンプルと比較してください。

最後に、私は複製、突然変異、および選択を追加しますが、今は自分の適応機能に問題があります。分割は、シャッフル、および再結合配列は、次のエラーが発生し、元の入力とは異なる寸法のものである:二番目の配列の

$ ValueError: operands could not be broadcast together with shapes (1273382) (1138213) 

寸法は、私がプログラムを実行するたびに変化するが、周りに常に1138000- 1145000。分割、シャッフル、再結合のステップでいくつかのチャンクを失ったように見えますが、ステップ3のどこかでリストの理解度を間違って使用していると思われますが、どこか理由が分かりません。何が間違っていますか?

# Import scipy audio tools, numpy, and randomization tools 
import scipy 
from scipy.io import wavfile 

import numpy 

from random import shuffle, randint 

# Read a wav file data array, detect zero crossings, split at zero crossings, and return a nested list. 
def process_wav(input): 

    # Assign the wavefile data array to a variable. 
    wavdata = input[1] 

    # Detect zero crossings, i.e. changes in sign in the waveform data. The line below returns an array of the indices of elements after which a zero crossing occurs. 
    zerocrossings = numpy.where(numpy.diff(numpy.sign(wavdata)))[0] 
    # Increment each element in the array by one. Otherwise, the indices are off. 
    zerocrossings = numpy.add(numpy.ones(zerocrossings.size, zerocrossings.dtype), zerocrossings) 

    wavdatalist = wavdata.tolist() 
    zerocrossingslist = zerocrossings.tolist() 

    # Split the list at zero crossings. The function below splits a list at the given indices.  
    def partition(alist, indices): 
     return [alist[i:j] for i, j in zip([0]+indices, indices+[None])] 

    return partition(wavdatalist, zerocrossingslist) 


# Accept a list as input, separate into positive and negative chunks, shuffle, and return a shuffled nested list 
def shuffle_wav(list): 

    # Separate waveform chunks into positive and negative lists. 
    positivechunks = [] 
    negativechunks = [] 

    for chunk in list: 
     if chunk[0] < 0: 
      negativechunks.append(chunk) 
     elif chunk[0] > 0: 
      positivechunks.append(chunk) 
     elif chunk[0] == 0: 
      positivechunks.append(chunk) 

    # Shuffle the chunks and append them to a list, alternating positive with negative. 
    shuffledchunks = [] 
    while len(positivechunks) >= 0 and len(negativechunks) > 0: 
     currentpositivechunk = positivechunks.pop(randint(0, len(positivechunks)-1)) 
     shuffledchunks.append(currentpositivechunk) 
     currentnegativechunk = negativechunks.pop(randint(0, len(negativechunks)-1)) 
     shuffledchunks.append(currentnegativechunk) 

    return [chunk for sublist in shuffledchunks for chunk in sublist] 

def get_fitness(array, target): 
    return numpy.square(numpy.subtract(target, array)) 

# Read a sample wav file. The wavfile function returns a tuple of the file's sample rate and data as a numpy array, to be passed to the process_wav() function. 
input = scipy.io.wavfile.read('sample.wav')  

wavchunks = process_wav(input) 
shuffledlist = shuffle_wav(wavchunks) 
output = numpy.array(shuffledlist, dtype='int16') 
print get_fitness(output, input[1]) 

scipy.io.wavfile.write('output.wav', 44100, output) 

編集:ここでは、完全なトレースバックです:

Traceback (most recent call last): 
    File "evowav.py", line 64, in <module> 
    print get_fitness(output, input[1]) 
    File "evowav.py", line 56, in get_fitness 
    return numpy.square(numpy.subtract(target, array)) 
ValueError: operands could not be broadcast together with shapes (1273382) (1136678)` 
+0

してくださいは、常にCOMPLETEトレースバックが含まれ、あるいは我々は助けることはできません。 –

+0

お詫び申し上げます。私は上記の完全なトレースバックを追加しました。 – ecmendenhall

+0

使用している.wavファイルへのリンクがあるので、再現できますか? –

答えて

1

まず第一に、のは、あなたのコードの一部をクリーンアップしましょう。

  1. は変数名としてそれらを使用することにより、このようなlistinputとしてPythonの組み込み関数を上書きしないでください。 Pythonは厳密にそれを防ぐわけではありませんが、後で驚きを引き起こします。

  2. z = numpy.add(x, y)などの明示的な呼び出しは必要ありません。 z = x + yははるかにpythonicと正確に同等です。 (xとはnumpy配列であると仮定します)同様に、numpy配列の各項目に1を加算するだけで、新しい配列を作成する必要はありません。コピーが必要な場合は、x += 1またはx = x + 1に電話してください。

  3. 定義の上に関数が何を行うかについてのコメントを入れるのではなく、以下に記載します。 Pythonのビルトインヘルプとドキュメンテーションツールは、最初のコメント(または複数行の文字列)の場合にのみ、これらの "docstrings"を利用することができるため、これは単なるスタイルコンベンションだけではありません。三重引用符)以下関数定義。 @talonmiesノートとして

、あなたの問題は、あなたが正と負のチャンクの数が同じであると仮定しているという事実から来ています。この問題を回避する方法はいくつかありますが、単純なものはitertools.izip_longestだけです。私達はちょうど何かが起こるべきか、なぜ推測されているので、

は今、一例として...

import random 
import itertools 
import numpy 
import scipy.io.wavfile 

def main(): 
    """Read a wav file and shuffle the negative and positive pieces.""" 
    # Use unpacking to your advantage, and avoid using "input" as a var name 
    samplerate, data = scipy.io.wavfile.read('sample.wav')  

    # Note, my sample.wav is stereo, so I'm going to just work with one channel 
    # If yours is mono, you'd want to just pass "data" directly in 
    left, right = data.T 

    wavchunks = process_wav(left) 
    output = shuffle_wav(wavchunks).astype(numpy.int16) 
    print get_fitness(output, samplerate) 

    scipy.io.wavfile.write('output.wav', 44100, output) 

def process_wav(wavdata): 
    """Read a wav file data array, detect zero crossings, 
    split at zero crossings, and return a list of numpy arrays""" 

    # I prefer nonzero to where, but either works in this case... 
    zerocrossings, = numpy.diff(numpy.sign(wavdata)).nonzero() 
    zerocrossings += 1 
    indicies = [0] + zerocrossings.tolist() + [None] 

    # The key is that we don't need to convert everything to a list. 
    # Just pass back a list of views into the array. This uses less memory. 
    return [wavdata[i:j] for i, j in zip(indicies[:-1], indicies[1:])] 

def shuffle_wav(partitions): 
    """Accept a list as input, separate into positive and negative chunks, 
    shuffle, and return a shuffled nested list.""" 

    # Instead of iterating through each item, just use indexing 
    poschunks = partitions[::2] 
    negchunks = partitions[1::2] 
    if poschunks[0][0] < 0: 
     # Reverse the variable names if the first chunk wasn't positive. 
     negchunks, poschunks = poschunks, negchunks 

    # Instead of popping a random index off, just shuffle the lists... 
    random.shuffle(poschunks) 
    random.shuffle(negchunks) 

    # To avoid the error you were getting, use izip_longest 
    chunks = itertools.izip_longest(poschunks, negchunks, fillvalue=[]) 

    return numpy.hstack(item for sublist in chunks for item in sublist) 


def get_fitness(array, target): 
    """Compares sum of square differences between the two arrays.""" 
    # I'm going to assume that you wanted a single sum returned here... 
    # Your original code returned an array. 
    return ((array - target)**2).sum() 

main() 
+0

ありがとう、ジョー!私はいつもitertoolsを怖がっていましたが、それは学ぶべき時です - それは多くの問題を解決するようです。あなたのスタイルノートは特に便利でした。私はゆっくりと物事をピジョンソニックに保つ方法を学んでいます。 – ecmendenhall

関連する問題