{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ThinkDSP\n",
"\n",
"This notebook contains solutions to exercises in Chapter 2: Harmonics\n",
"\n",
"Copyright 2015 Allen Downey\n",
"\n",
"License: [Creative Commons Attribution 4.0 International](http://creativecommons.org/licenses/by/4.0/)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"# Get thinkdsp.py\n",
"\n",
"import os\n",
"\n",
"if not os.path.exists('thinkdsp.py'):\n",
" !wget https://github.com/AllenDowney/ThinkDSP/raw/master/code/thinkdsp.py"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from thinkdsp import decorate"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1\n",
"\n",
"A sawtooth signal has a waveform that ramps up linearly from -1 to 1, then drops to -1 and repeats. See http://en.wikipedia.org/wiki/Sawtooth_wave\n",
"\n",
"Write a class called `SawtoothSignal` that extends `Signal` and provides `evaluate` to evaluate a sawtooth signal.\n",
"\n",
"Compute the spectrum of a sawtooth wave. How does the harmonic structure compare to triangle and square waves? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Solution\n",
"\n",
"My solution is basically a simplified version of TriangleSignal."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"from thinkdsp import Sinusoid\n",
"from thinkdsp import normalize, unbias\n",
"import numpy as np\n",
"\n",
"class SawtoothSignal(Sinusoid):\n",
" \"\"\"Represents a sawtooth signal.\"\"\"\n",
" \n",
" def evaluate(self, ts):\n",
" \"\"\"Evaluates the signal at the given times.\n",
"\n",
" ts: float array of times\n",
" \n",
" returns: float wave array\n",
" \"\"\"\n",
" cycles = self.freq * ts + self.offset / np.pi / 2\n",
" frac, _ = np.modf(cycles)\n",
" ys = normalize(unbias(frac), self.amp)\n",
" return ys"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's what it sounds like:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
" \n",
" "
],
"text/plain": [
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sawtooth = SawtoothSignal().make_wave(duration=0.5, framerate=40000)\n",
"sawtooth.make_audio()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here's what the spectrum looks like:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"