<jupyter_start><jupyter_text>Sine Wave DerivationHow to make a sine wave and write it to a WAV file with NumPy and SciPy<jupyter_code>import numpy as np
from scipy.io.wavfile import write<jupyter_output><empty_output><jupyter_text>Our starting variables`sps`: The number of samples per second. Units: **sample s-1**`freq`: Frequency of sine wave in Hz. Units: **s-1**The waveform will osciallte between -1.0 and +1.0 Putting it togetherFirst we need to express the frequency in terms of angular frequency, recalling that there are **2π rad** in each cycle **(`freq` s-1)(2π rad) = 2π rad `freq` s-1**If we switch to the period of the waeform, we can have something like:**1 / (2π rad * `freq` s-1)**This is convenient because we need to compute values in terms of sample number, and we need **s-1** to cancel. Hence:**(`sps` sample s-1) / (2π rad * `freq` s-1) = (`sps` sample) / (2π rad * `freq`) **But ultimately we want to express the frequency to generate in Hz, not period, so we invert again:**(2π rad * `freq` ) / (`sps` sample)**Finally, I will say that**Si** is the value of the waveform at sample *i*. Unit *sample* (OK, probably not the best use of units)**Si sample = (2π rad `freq`) / (`sps` sample)**Since **2π rad** is a constant, and samples cancel, I can gather some terms and obtain:**Si sample = (2π rad) `freq` / `sps`**Now we are ready for some NumPy! Using NumPyNumPy is going to be vectorized, which means it computes many values at once. So instead of explicitly iterating over a list of samples, we will make an implicit loop by first generating an array of sample numbers for NumPy to do further caluclations with.We will need to specify a duration though:`duration_s`: The duration in seconds. Units **s**Therefore the total sample we will need to compute are **`sps` sample s-1 * `duration_s` s**Proceed by declaring our variables<jupyter_code>sps = 44100
freq = 440
duration_s = 3.0<jupyter_output><empty_output><jupyter_text>Now we make a NumPy array that has each sample we need to calculate. Then we can place it inside the expression that will calculate the entire waveform, like so:<jupyter_code>each_sample_number = np.arange(sps * duration_s)
waveform = np.sin(2 * np.pi * each_sample_number * freq / sps)<jupyter_output><empty_output><jupyter_text>Our waveform is in floating points between -1.0 and +1.0. To make a wave file I need signed integers.<jupyter_code>waveform_integers = np.int16(waveform * 32767)<jupyter_output><empty_output><jupyter_text>Now I can finally write the file to an output (see the top of the file for where write comes from)<jupyter_code>write('test.wav', 44100, waveform_integers)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09869158878504673, 'fraction_numerical': 0.019065420560747663, 'mean_word_length': 5.137614678899083, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '289794', 'license': 'BSD-2-Clause', 'n_tokens_mistral': 866, 'n_tokens_neox': 815, 'n_words': 368, 'path': 'notebooks/sine-wave-derivation.ipynb', 'repo_name': 'alicialink/synth-junction', 'size': '2675'}