Browse Source

Audio

pull/144/merge 3.8
Jure Šorn 7 months ago
parent
commit
335fcd1db8
3 changed files with 59 additions and 45 deletions
  1. 42
      README.md
  2. 44
      index.html
  3. 18
      parse.js

42
README.md

@ -2867,7 +2867,7 @@ import wave
``` ```
```python ```python
<Wave> = wave.open('<path>', 'rb') # Opens the WAV file.
<Wave> = wave.open('<path>') # Opens the WAV file for reading.
<int> = <Wave>.getframerate() # Returns number of frames per second. <int> = <Wave>.getframerate() # Returns number of frames per second.
<int> = <Wave>.getnchannels() # Returns number of samples per frame. <int> = <Wave>.getnchannels() # Returns number of samples per frame.
<int> = <Wave>.getsampwidth() # Returns number of bytes per sample. <int> = <Wave>.getsampwidth() # Returns number of bytes per sample.
@ -2880,7 +2880,7 @@ import wave
<Wave>.setframerate(<int>) # Pass 44100 for CD, 48000 for video. <Wave>.setframerate(<int>) # Pass 44100 for CD, 48000 for video.
<Wave>.setnchannels(<int>) # Pass 1 for mono, 2 for stereo. <Wave>.setnchannels(<int>) # Pass 1 for mono, 2 for stereo.
<Wave>.setsampwidth(<int>) # Pass 2 for CD, 3 for hi-res sound. <Wave>.setsampwidth(<int>) # Pass 2 for CD, 3 for hi-res sound.
<Wave>.setparams(<tuple>) # Sets all parameters.
<Wave>.setparams(<tuple>) # Tuple must contain all parameters.
<Wave>.writeframes(<bytes>) # Appends frames to the file. <Wave>.writeframes(<bytes>) # Appends frames to the file.
``` ```
* **Bytes object contains a sequence of frames, each consisting of one or more samples.** * **Bytes object contains a sequence of frames, each consisting of one or more samples.**
@ -2904,28 +2904,28 @@ import wave
```python ```python
def read_wav_file(filename): def read_wav_file(filename):
def get_int(bytes_obj): def get_int(bytes_obj):
an_int = int.from_bytes(bytes_obj, 'little', signed=(sampwidth != 1))
return an_int - 128 * (sampwidth == 1)
with wave.open(filename, 'rb') as file:
sampwidth = file.getsampwidth()
an_int = int.from_bytes(bytes_obj, 'little', signed=(p.sampwidth != 1))
return an_int - 128 * (p.sampwidth == 1)
with wave.open(filename) as file:
p = file.getparams()
frames = file.readframes(-1) frames = file.readframes(-1)
bytes_samples = (frames[i : i+sampwidth] for i in range(0, len(frames), sampwidth))
return [get_int(b) / pow(2, sampwidth * 8 - 1) for b in bytes_samples]
bytes_samples = (frames[i : i + p.sampwidth] for i in range(0, len(frames), p.sampwidth))
return [get_int(b) / pow(2, p.sampwidth * 8 - 1) for b in bytes_samples], p
``` ```
### Write Float Samples to WAV File ### Write Float Samples to WAV File
```python ```python
def write_to_wav_file(filename, float_samples, nchannels=1, sampwidth=2, framerate=44100):
def write_to_wav_file(filename, samples_f, p=None, nchannels=1, sampwidth=2, framerate=44100):
def get_bytes(a_float): def get_bytes(a_float):
a_float = max(-1, min(1 - 2e-16, a_float)) a_float = max(-1, min(1 - 2e-16, a_float))
a_float += sampwidth == 1
a_float *= pow(2, sampwidth * 8 - 1)
return int(a_float).to_bytes(sampwidth, 'little', signed=(sampwidth != 1))
a_float += p.sampwidth == 1
a_float *= pow(2, p.sampwidth * 8 - 1)
return int(a_float).to_bytes(p.sampwidth, 'little', signed=(p.sampwidth != 1))
if p is None:
p = wave._wave_params(nchannels, sampwidth, framerate, 0, 'NONE', 'not compressed')
with wave.open(filename, 'wb') as file: with wave.open(filename, 'wb') as file:
file.setnchannels(nchannels)
file.setsampwidth(sampwidth)
file.setframerate(framerate)
file.writeframes(b''.join(get_bytes(f) for f in float_samples))
file.setparams(p)
file.writeframes(b''.join(get_bytes(f) for f in samples_f))
``` ```
### Examples ### Examples
@ -2936,12 +2936,12 @@ samples_f = (sin(i * 2 * pi * 440 / 44100) for i in range(100_000))
write_to_wav_file('test.wav', samples_f) write_to_wav_file('test.wav', samples_f)
``` ```
#### Adds noise to the mono WAV file:
#### Adds noise to the WAV file:
```python ```python
from random import random
add_noise = lambda value: value + (random() - 0.5) * 0.03
samples_f = (add_noise(f) for f in read_wav_file('test.wav'))
write_to_wav_file('test.wav', samples_f)
from random import uniform
samples_f, params = read_wav_file('test.wav')
samples_f = (f + uniform(-0.05, 0.05) for f in samples_f)
write_to_wav_file('test.wav', samples_f, params)
``` ```
#### Plays the WAV file: #### Plays the WAV file:

44
index.html

@ -54,7 +54,7 @@
<body> <body>
<header> <header>
<aside>October 2, 2024</aside>
<aside>October 3, 2024</aside>
<a href="https://gto76.github.io" rel="author">Jure Šorn</a> <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
</header> </header>
@ -2340,7 +2340,7 @@ imageio.mimsave(<span class="hljs-string">'test.gif'</span>, frames, duration=<s
<div><h2 id="audio"><a href="#audio" name="audio">#</a>Audio</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> wave <div><h2 id="audio"><a href="#audio" name="audio">#</a>Audio</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> wave
</code></pre></div> </code></pre></div>
<pre><code class="python language-python hljs">&lt;Wave&gt; = wave.open(<span class="hljs-string">'&lt;path&gt;'</span>, <span class="hljs-string">'rb'</span>) <span class="hljs-comment"># Opens the WAV file.</span>
<pre><code class="python language-python hljs">&lt;Wave&gt; = wave.open(<span class="hljs-string">'&lt;path&gt;'</span>) <span class="hljs-comment"># Opens the WAV file for reading.</span>
&lt;int&gt; = &lt;Wave&gt;.getframerate() <span class="hljs-comment"># Returns number of frames per second.</span> &lt;int&gt; = &lt;Wave&gt;.getframerate() <span class="hljs-comment"># Returns number of frames per second.</span>
&lt;int&gt; = &lt;Wave&gt;.getnchannels() <span class="hljs-comment"># Returns number of samples per frame.</span> &lt;int&gt; = &lt;Wave&gt;.getnchannels() <span class="hljs-comment"># Returns number of samples per frame.</span>
&lt;int&gt; = &lt;Wave&gt;.getsampwidth() <span class="hljs-comment"># Returns number of bytes per sample.</span> &lt;int&gt; = &lt;Wave&gt;.getsampwidth() <span class="hljs-comment"># Returns number of bytes per sample.</span>
@ -2351,7 +2351,7 @@ imageio.mimsave(<span class="hljs-string">'test.gif'</span>, frames, duration=<s
&lt;Wave&gt;.setframerate(&lt;int&gt;) <span class="hljs-comment"># Pass 44100 for CD, 48000 for video.</span> &lt;Wave&gt;.setframerate(&lt;int&gt;) <span class="hljs-comment"># Pass 44100 for CD, 48000 for video.</span>
&lt;Wave&gt;.setnchannels(&lt;int&gt;) <span class="hljs-comment"># Pass 1 for mono, 2 for stereo.</span> &lt;Wave&gt;.setnchannels(&lt;int&gt;) <span class="hljs-comment"># Pass 1 for mono, 2 for stereo.</span>
&lt;Wave&gt;.setsampwidth(&lt;int&gt;) <span class="hljs-comment"># Pass 2 for CD, 3 for hi-res sound.</span> &lt;Wave&gt;.setsampwidth(&lt;int&gt;) <span class="hljs-comment"># Pass 2 for CD, 3 for hi-res sound.</span>
&lt;Wave&gt;.setparams(&lt;tuple&gt;) <span class="hljs-comment"># Sets all parameters.</span>
&lt;Wave&gt;.setparams(&lt;tuple&gt;) <span class="hljs-comment"># Tuple must contain all parameters.</span>
&lt;Wave&gt;.writeframes(&lt;bytes&gt;) <span class="hljs-comment"># Appends frames to the file.</span> &lt;Wave&gt;.writeframes(&lt;bytes&gt;) <span class="hljs-comment"># Appends frames to the file.</span>
</code></pre> </code></pre>
<ul> <ul>
@ -2372,26 +2372,26 @@ imageio.mimsave(<span class="hljs-string">'test.gif'</span>, frames, duration=<s
<div><h3 id="readfloatsamplesfromwavfile">Read Float Samples from WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_wav_file</span><span class="hljs-params">(filename)</span>:</span> <div><h3 id="readfloatsamplesfromwavfile">Read Float Samples from WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_wav_file</span><span class="hljs-params">(filename)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_int</span><span class="hljs-params">(bytes_obj)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_int</span><span class="hljs-params">(bytes_obj)</span>:</span>
an_int = int.from_bytes(bytes_obj, <span class="hljs-string">'little'</span>, signed=(sampwidth != <span class="hljs-number">1</span>))
<span class="hljs-keyword">return</span> an_int - <span class="hljs-number">128</span> * (sampwidth == <span class="hljs-number">1</span>)
<span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> file:
sampwidth = file.getsampwidth()
an_int = int.from_bytes(bytes_obj, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>))
<span class="hljs-keyword">return</span> an_int - <span class="hljs-number">128</span> * (p.sampwidth == <span class="hljs-number">1</span>)
<span class="hljs-keyword">with</span> wave.open(filename) <span class="hljs-keyword">as</span> file:
p = file.getparams()
frames = file.readframes(<span class="hljs-number">-1</span>) frames = file.readframes(<span class="hljs-number">-1</span>)
bytes_samples = (frames[i : i+sampwidth] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(frames), sampwidth))
<span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> bytes_samples]
bytes_samples = (frames[i : i + p.sampwidth] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(frames), p.sampwidth))
<span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> bytes_samples], p
</code></pre></div> </code></pre></div>
<div><h3 id="writefloatsamplestowavfile">Write Float Samples to WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, float_samples, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span>
<div><h3 id="writefloatsamplestowavfile">Write Float Samples to WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, samples_f, p=<span class="hljs-keyword">None</span>, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span>
a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float)) a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float))
a_float += sampwidth == <span class="hljs-number">1</span>
a_float *= pow(<span class="hljs-number">2</span>, sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>)
<span class="hljs-keyword">return</span> int(a_float).to_bytes(sampwidth, <span class="hljs-string">'little'</span>, signed=(sampwidth != <span class="hljs-number">1</span>))
a_float += p.sampwidth == <span class="hljs-number">1</span>
a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>)
<span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>))
<span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>:
p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">'NONE'</span>, <span class="hljs-string">'not compressed'</span>)
<span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file:
file.setnchannels(nchannels)
file.setsampwidth(sampwidth)
file.setframerate(framerate)
file.writeframes(<span class="hljs-string">b''</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> float_samples))
file.setparams(p)
file.writeframes(<span class="hljs-string">b''</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f))
</code></pre></div> </code></pre></div>
<div><h3 id="examples-1">Examples</h3><div><h4 id="savesa440hzsinewavetoamonowavfile">Saves a 440 Hz sine wave to a mono WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, sin <div><h3 id="examples-1">Examples</h3><div><h4 id="savesa440hzsinewavetoamonowavfile">Saves a 440 Hz sine wave to a mono WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, sin
@ -2400,10 +2400,10 @@ write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f)
</code></pre></div></div> </code></pre></div></div>
<div><h4 id="addsnoisetothemonowavfile">Adds noise to the mono WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random
add_noise = <span class="hljs-keyword">lambda</span> value: value + (random() - <span class="hljs-number">0.5</span>) * <span class="hljs-number">0.03</span>
samples_f = (add_noise(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> read_wav_file(<span class="hljs-string">'test.wav'</span>))
write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f)
<div><h4 id="addsnoisetothewavfile">Adds noise to the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> uniform
samples_f, params = read_wav_file(<span class="hljs-string">'test.wav'</span>)
samples_f = (f + uniform(<span class="hljs-number">-0.05</span>, <span class="hljs-number">0.05</span>) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f)
write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f, params)
</code></pre></div> </code></pre></div>
<div><h4 id="playsthewavfile">Plays the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install simpleaudio</span> <div><h4 id="playsthewavfile">Plays the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install simpleaudio</span>
@ -2931,7 +2931,7 @@ $ deactivate <span class="hljs-comment"># Deactivates the active
<footer> <footer>
<aside>October 2, 2024</aside>
<aside>October 3, 2024</aside>
<a href="https://gto76.github.io" rel="author">Jure Šorn</a> <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
</footer> </footer>

18
parse.js

@ -220,7 +220,20 @@ const LOGGING_EXAMPLE =
'<span class="hljs-meta">&gt;&gt;&gt; </span>print(open(<span class="hljs-string">\'test.log\'</span>).read())\n' + '<span class="hljs-meta">&gt;&gt;&gt; </span>print(open(<span class="hljs-string">\'test.log\'</span>).read())\n' +
'2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.\n'; '2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.\n';
const AUDIO =
const AUDIO_1 =
'<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, samples_f, p=<span class="hljs-keyword">None</span>, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span>\n' +
' <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span>\n' +
' a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float))\n' +
' a_float += p.sampwidth == <span class="hljs-number">1</span>\n' +
' a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>)\n' +
' <span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">\'little\'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>))\n' +
' <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>:\n' +
' p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">\'NONE\'</span>, <span class="hljs-string">\'not compressed\'</span>)\n' +
' <span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">\'wb\'</span>) <span class="hljs-keyword">as</span> file:\n' +
' file.setparams(p)\n' +
' file.writeframes(<span class="hljs-string">b\'\'</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f))\n';
const AUDIO_2 =
'<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, sin\n' + '<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, sin\n' +
'samples_f = (sin(i * <span class="hljs-number">2</span> * pi * <span class="hljs-number">440</span> / <span class="hljs-number">44100</span>) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">100_000</span>))\n' + 'samples_f = (sin(i * <span class="hljs-number">2</span> * pi * <span class="hljs-number">440</span> / <span class="hljs-number">44100</span>) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">100_000</span>))\n' +
'write_to_wav_file(<span class="hljs-string">\'test.wav\'</span>, samples_f)\n'; 'write_to_wav_file(<span class="hljs-string">\'test.wav\'</span>, samples_f)\n';
@ -839,7 +852,8 @@ function fixHighlights() {
$(`code:contains(import curses, os)`).html(CURSES); $(`code:contains(import curses, os)`).html(CURSES);
$(`code:contains(pip3 install tqdm)`).html(PROGRESS_BAR); $(`code:contains(pip3 install tqdm)`).html(PROGRESS_BAR);
$(`code:contains(>>> log.basicConfig()`).html(LOGGING_EXAMPLE); $(`code:contains(>>> log.basicConfig()`).html(LOGGING_EXAMPLE);
$(`code:contains(samples_f = (sin(i *)`).html(AUDIO);
$(`code:contains(a_float = max()`).html(AUDIO_1);
$(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
$(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO); $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
$(`code:contains(>>> gb = df.groupby)`).html(GROUPBY); $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
$(`code:contains(cdef <ctype> <var_name> = <obj>)`).html(CYTHON_1); $(`code:contains(cdef <ctype> <var_name> = <obj>)`).html(CYTHON_1);

Loading…
Cancel
Save