'NumPy adds a dot after each element of an array which I can’t strip

I am trying to write code which generates a sound file based on a series of frequencies I give it, but I have reached a point where compiling the arrays of integer values together puts a decimal point after each one which corrupts the sound file I'm generating.

I've tried converting it into a list, turning all elements into integer values, and then converting it back. This removes the dots, but it still corrupts the file.

Here is my code:

import numpy as np
from scipy.io.wavfile import write

# Samples per second
sps = 44100

# Duration
duration = 0.1

def wavegen(build):
    final_array = np.array([])
    for i in build:
        freq = i
        eachnum = np.arange(duration * sps)
        waveform = np.sin(2 * np.pi * eachnum * freq / sps)
        waveform_quiet = waveform * 0.3
        waveform_integers = np.int16(waveform_quiet * 32767)
        final_array  = np.append(final_array, waveform_integers)

    print(final_array)
    write('sine.wav', sps, final_array)

wavegen([100, 50, 100, 50])

And the array generated looks like this:

[   0.  140.  280. ... -210. -140.  -70.]


Solution 1:[1]

The reason that you are getting the decimal places is because final_array = np.array([]) is creating a float type array. When you append your integer array waveform_integers with the float type array final_array, you get a float type array because final_array is set to use floats.

To fix this, you can use final_array = np.array([], dtype='int16') which will make it so that both arrays in np.append are int16 arrays and the result is also an int16 array.

Solution 2:[2]

The use of np.append in a loop is inefficient. List append is better, since it works in-place. np.append is a cover function for np.concatenate, which makes a whole new array (with all the involved copying) each call.

def wavegen(build):
    alist = []
    for i in build:
        freq = i
        eachnum = np.arange(duration * sps)
        waveform = np.sin(2 * np.pi * eachnum * freq / sps)
        waveform_quiet = waveform * 0.3
        alist.append(waveform_integers * 32767)
    final_array = np.array(alist)      # 2d result
    # or final_array = np.hstack(alist)     # 1d
    final_array = final_array.astype(np.int16)  # change the dtype just once
    return final_array

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Mortensen
Solution 2