How to generate a sine wave in python? - python-3.x

To generate a csv file where each column is a data of sine wave of frequency 1 Hz, 2 Hz, 3Hz, 4Hz, 5Hz, 6Hz and 7 Hz. The amplitude is one volt. There should be 100 points in one cycle and thus 700 points in seven waves.

Here is how I will go about it:
import pandas as pd
import numpy as np
freqs = list(range(1, 9))
time = np.linspace(0, 2*np.pi, 100)
data = {f"{freq}Hz": np.sin(2 * np.pi * freq * time) for freq in freqs}
df = pd.DataFrame(data)
df.head()

Related

How to multiply an audio signal from wav file by a fixed sine wave in Python3?

I have some audio stream in a Wav file and I need to multiply it by a fixed sine wave at a given frequency. Also, the volume of the input Wav should not differ from the volume of the sinusoidal signal. How can i do this?
I was able to do the multiplication of one sinusoid by another, but did not understand how to do the multiplication of data from a wav file.
import wave, os, bitstring
import numpy as np
from matplotlib import pyplot as plt
SAMPLE_RATE = 41600 # Hertz
DURATION = 578 # Seconds
def generate_sine_wave(freq, sample_rate, duration):
x = np.linspace(0, duration, sample_rate * duration, endpoint=False)
frequencies = x * freq
# 2pi because np.sin takes radians
y = np.sin((2 * np.pi) * frequencies)
return x, y
_, nice_tone = generate_sine_wave(1, SAMPLE_RATE, DURATION)
_, noise_tone = generate_sine_wave(50, SAMPLE_RATE, DURATION)
noise_tone = noise_tone * 0.3
mixed_tone = nice_tone + noise_tone
Plt img

How to process output into signed 16-bit big-endian integers

need to make this equation output the data as signed 16-bit big-endian integers for a wave (WAV) file: how is the most efficient way to express that in this equation?
import numpy as np
import pyglet
import sox
# sample rate in Hz
sample_rate = 44100
# generate a 1-second sine tone at 440 Hz
y = np.sin(2 * np.pi * 440.0 * np.arange(sample_rate * 1.0) / sample_rate)
print(y) #prints first and last in array y (its floating point)
# really need signed 16 bit big endian integers for a wave file

Why does librosa STFT show wrong frequencies?

I generated a 200 Hz sine wave using numpy and then used librosas stft() and specshow() functions to show a spectrogram. However, the frequency it is showing is not 200 Hz. When I use matplotlibs magnitude_spectrum() function, it shows exactly 200 Hz. Does anyone know why that might be? Am I doing something wrong? Any help will be much appriciated.
The results from librosas spectrogram and matplotlibs frequency spectrum can be seen in the image below.
Minimal working example:
import matplotlib.pyplot as plt
from matplotlib import mlab
%matplotlib inline
import numpy as np
import librosa
import librosa.display
sr = 20000
freq1 = 200
n_fft=2000
x = np.linspace(0, 1, sr)
y = 0.5*np.sin(freq1 * 2 * np.pi * x)
no_window = np.linspace(1, 1, n_fft)
D = np.abs(librosa.stft(y, n_fft=n_fft, hop_length=int(n_fft/2), window=no_window, center=False,))
plt.figure(figsize=(9, 4))
librosa.display.specshow(D, y_axis='linear')
plt.xlabel('Time [s]')
plt.ylabel('Frequency [Hz]')
plt.ylim(0, 250)
plt.tight_layout()
plt.show()
plt.figure(figsize=(9, 4))
plt.magnitude_spectrum(y, Fs=sr, color='C1', window=mlab.window_none)
plt.xlim(0, 250)
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitude [-]')
plt.tight_layout()
plt.show()
Just passing the results to specshow is not enough. You also need to tell it what scale these results are on. You do this be passing the sample rate parameter sr like this:
librosa.display.specshow(D, y_axis='linear', sr=sr)
If you don't, it defaults to sr=22050, hop_length=512, which is certainly not correct in your case.
This is similar to the answer given here.

FFT freq wrong is there a problem in code

Want to convert raw accelerometer data to frequency however I have set the frequency on my motor to 120hz and check with another device I am unable to FFT the accelerometer data to get the right frequency produced by the motor
Using Python 3.7, the data use is most likely correct so wondering if there is a problem in the code
from scipy.fftpack import fft
import numpy as np
from scipy import pi
import matplotlib.pyplot as plt
%matplotlib inline
# Sampling rate and time vector
start_time = 0 # seconds
end_time = 2 # seconds
sampling_rate = 6660 # Hz
N =(end_time - start_time)*sampling_rate # array size
# Nyquist Sampling Criteria
T = 1/sampling_rate # inverse of the sampling rate
x = np.linspace(0.0, 1.0/(2.0*T), int(N/2))
# FFT algorithm
yr = fft(X) # "raw" FFT with both + and - frequencies
y = 2/N * np.abs(yr[0:np.int(N/2)]) # positive freqs only
# Plotting the results
plt.plot(x, y)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Vibration (g)')

What is the meaning/scale for the amplitude in a Numpy FFT?

To the best of my knowledge, the amplitude in an FFT is 10 times its corresponding frequency. For example, if you were to take the FFT of sin(t) from 0 to 2*pi, the FFT would peak at a frequency of .159 Hz and have a corresponding amplitude of 1.59. However, when I add sin(2*t) to sin(t)--y = sin(t) + sin(2*t)--the amplitudes are no longer 10 times the frequencies. Why is that? Thank you in advance for your help.
The image isn't all that helpful but the 2 amplitudes are less than they should be assuming the amplitude is supposed to be 10 times the frequency.
import math
import numpy as np[enter image description here][1]
import numpy.fft as fft
import matplotlib.pyplot as plt
t = np.linspace(0, 2*math.pi, 1600)
y = np.sin(t) + np.sin(2*t)
plt.plot(t, y)
plt.xlabel('time')
plt.ylabel('height')
plt.show()
fft_power = fft.fft(y)
rfft_power = fft.rfft(y)
sample_spacing = 3.92944672e-03
frequency = fft.fftfreq(len(fft_power), sample_spacing)
real_frequency = fft.rfftfreq(len(fft_power), sample_spacing)
plt.plot(real_frequency.real, rfft_power.real, 'ro')
plt.xlabel('frequency')
plt.ylabel('amplitude')
plt.show()

Resources