音つくる。
import numpy as np
from IPython.display import Audio
# パラメータ設定
fs = 44100 # サンプリングレート
duration = 1.0 # 音の持続時間(秒)
frequency = 440.0 # サイン波の周波数(Hz)
# サイン波の生成
t = np.linspace(0, duration, int(fs * duration), endpoint=False)
audio = 0.5 * np.sin(2 * np.pi * frequency * t)
# オーディオの再生
Audio(audio, rate=fs, autoplay=True)
パラメータ設定
fs = 44100 # サンプリングレート
duration = 1.0 # 音の持続時間(秒)
frequency = 440.0 # サイン波の周波数(Hz)
fs: サンプリングレート。1秒間に44100回サンプリングすることを意味します。これはCD音質の標準的なレートです。
duration: 音の持続時間。ここでは1秒間の音を生成します。
frequency: サイン波の周波数。440Hzは標準的なA音(ラ)です。
サイン波の生成
t = np.linspace(0, duration, int(fs * duration), endpoint=False)
audio = 0.5 * np.sin(2 * np.pi * frequency * t)
t: 0から`duration`秒までの間の時間を等間隔に分割した配列を生成します。この場合、44100個の点を持つ配列になります。
audio: サイン波を生成します。`0.5`は音量の調整で、振幅を半分にしています。`np.sin(2 * np.pi * frequency * t)`はサイン波の生成式です。
np.linspace
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
np.linspaceは、指定した範囲の数値を均等に分割して配列を作成する関数です。
start: 配列の開始値
stop: 配列の終了値
num: 生成する数値の数(デフォルトは50)
endpoint: Trueの場合、stopを配列に含めます。Falseの場合、stopを含めません。
retstep: Trueの場合、生成された数値間の間隔も返します。
dtype: 配列のデータ型を指定します。
axis: 配列が生成される軸を指定します。
オーディオの再生
Audio(audio, rate=fs, autoplay=True)
`Audio`: 生成したサイン波データ`audio`を再生します。
`rate`: サンプリングレートを指定します。
`autoplay`: `True`にすることで、自動再生を有効にします。
このコードを実行すると、440Hzのサイン波(音)が1秒間再生されます。
音量
音量調整はサイン派の振幅
import numpy as np
from IPython.display import Audio
# パラメータ設定
fs = 44100 # サンプリングレート
duration = 1.0 # 音の持続時間(秒)
frequency = 440.0 # サイン波の周波数(Hz)
amplitude = 0.1 # サイン波の振幅(音量)
# サイン波の生成
t = np.linspace(0, duration, int(fs * duration), endpoint=False)
audio = amplitude * np.sin(2 * np.pi * frequency * t)
# オーディオの再生
Audio(audio, rate=fs, autoplay=True)
音階
音階の周波数は12音階の等比数列に従います。基準となるA4(440Hz)を基にして、それぞれの音の周波数を計算できます。以下に、一般的な音階の周波数をA4(440Hz)を基準として列挙します。
主要な音階の周波数
各オクターブの基準音$${A4}$$の周波数を基に、12音の音階を列挙します。計算には次の公式を使用します:
$${ f(n) = 440 \times 2^{\frac{n}{12}} }$$
ここで、$${ n }$$ はA4からの半音の数です。例えば、A#4はA4から1半音上がった音ですので、$${ n = 1 }$$ です。
A4 = 440Hz
C4 (261.63Hz)
C#4/Db4 (277.18Hz)
D4 (293.66Hz)
D#4/Eb4 (311.13Hz)
E4 (329.63Hz)
F4 (349.23Hz)
F#4/Gb4 (369.99Hz)
G4 (392.00Hz)
G#4/Ab4 (415.30Hz)
A4 (440.00Hz)
A#4/Bb4 (466.16Hz)
B4 (493.88Hz)
その他のオクターブの音階
各オクターブにおける音の周波数も同様に計算できます。例えば、C5はC4の1オクターブ上(倍の周波数)です。
C音のオクターブ
C0 (16.35Hz)
C1 (32.70Hz)
C2 (65.41Hz)
C3 (130.81Hz)
C4 (261.63Hz)
C5 (523.25Hz)
C6 (1046.50Hz)
C7 (2093.00Hz)
C8 (4186.01Hz)
D音のオクターブ
D0 (18.35Hz)
D1 (36.71Hz)
D2 (73.42Hz)
D3 (146.83Hz)
D4 (293.66Hz)
D5 (587.33Hz)
D6 (1174.66Hz)
D7 (2349.32Hz)
D8 (4698.64Hz)
html+JavaScript
なんかpython、音がでかい。
%%html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Melody Generator</title>
</head>
<body>
<h1>Melody Generator</h1>
<label for="note">Note:</label>
<select id="note">
<option value="16.35">C0</option>
<option value="17.32">C#0/Db0</option>
<option value="18.35">D0</option>
<option value="19.45">D#0/Eb0</option>
<option value="20.60">E0</option>
<option value="21.83">F0</option>
<option value="23.12">F#0/Gb0</option>
<option value="24.50">G0</option>
<option value="25.96">G#0/Ab0</option>
<option value="27.50">A0</option>
<option value="29.14">A#0/Bb0</option>
<option value="30.87">B0</option>
<option value="32.70">C1</option>
<option value="34.65">C#1/Db1</option>
<option value="36.71">D1</option>
<option value="38.89">D#1/Eb1</option>
<option value="41.20">E1</option>
<option value="43.65">F1</option>
<option value="46.25">F#1/Gb1</option>
<option value="49.00">G1</option>
<option value="51.91">G#1/Ab1</option>
<option value="55.00">A1</option>
<option value="58.27">A#1/Bb1</option>
<option value="61.74">B1</option>
<option value="65.41">C2</option>
<option value="69.30">C#2/Db2</option>
<option value="73.42">D2</option>
<option value="77.78">D#2/Eb2</option>
<option value="82.41">E2</option>
<option value="87.31">F2</option>
<option value="92.50">F#2/Gb2</option>
<option value="98.00">G2</option>
<option value="103.83">G#2/Ab2</option>
<option value="110.00">A2</option>
<option value="116.54">A#2/Bb2</option>
<option value="123.47">B2</option>
<option value="130.81">C3</option>
<option value="138.59">C#3/Db3</option>
<option value="146.83">D3</option>
<option value="155.56">D#3/Eb3</option>
<option value="164.81">E3</option>
<option value="174.61">F3</option>
<option value="185.00">F#3/Gb3</option>
<option value="196.00">G3</option>
<option value="207.65">G#3/Ab3</option>
<option value="220.00">A3</option>
<option value="233.08">A#3/Bb3</option>
<option value="246.94">B3</option>
<option value="261.63">C4</option>
<option value="277.18">C#4/Db4</option>
<option value="293.66">D4</option>
<option value="311.13">D#4/Eb4</option>
<option value="329.63">E4</option>
<option value="349.23">F4</option>
<option value="369.99">F#4/Gb4</option>
<option value="392.00">G4</option>
<option value="415.30">G#4/Ab4</option>
<option value="440.00">A4</option>
<option value="466.16">A#4/Bb4</option>
<option value="493.88">B4</option>
<option value="523.25">C5</option>
<option value="554.37">C#5/Db5</option>
<option value="587.33">D5</option>
<option value="622.25">D#5/Eb5</option>
<option value="659.25">E5</option>
<option value="698.46">F5</option>
<option value="739.99">F#5/Gb5</option>
<option value="783.99">G5</option>
<option value="830.61">G#5/Ab5</option>
<option value="880.00">A5</option>
<option value="932.33">A#5/Bb5</option>
<option value="987.77">B5</option>
<option value="1046.50">C6</option>
<option value="1108.73">C#6/Db6</option>
<option value="1174.66">D6</option>
<option value="1244.51">D#6/Eb6</option>
<option value="1318.51">E6</option>
<option value="1396.91">F6</option>
<option value="1479.98">F#6/Gb6</option>
<option value="1567.98">G6</option>
<option value="1661.22">G#6/Ab6</option>
<option value="1760.00">A6</option>
<option value="1864.66">A#6/Bb6</option>
<option value="1975.53">B6</option>
<option value="2093.00">C7</option>
<option value="2217.46">C#7/Db7</option>
<option value="2349.32">D7</option>
<option value="2489.02">D#7/Eb7</option>
<option value="2637.02">E7</option>
<option value="2793.83">F7</option>
<option value="2959.96">F#7/Gb7</option>
<option value="3135.96">G7</option>
<option value="3322.44">G#7/Ab7</option>
<option value="3520.00">A7</option>
<option value="3729.31">A#7/Bb7</option>
<option value="3951.07">B7</option>
<option value="4186.01">C8</option>
</select>
<label for="duration">Duration (s):</label>
<input type="range" id="duration" min="0.1" max="2.0" step="0.1" value="0.5">
<span id="durationValue">0.5</span>
<label for="volume">Volume:</label>
<input type="range" id="volume" min="0.0" max="1.0" step="0.1" value="0.5">
<span id="volumeValue">0.5</span>
<button id="addNote">Add Note</button>
<button id="playMelody">Play Melody</button>
<div id="melodyOutput"></div>
<script>
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
let melody = [];
document.getElementById('duration').addEventListener('input', function() {
document.getElementById('durationValue').textContent = this.value;
});
document.getElementById('volume').addEventListener('input', function() {
document.getElementById('volumeValue').textContent = this.value;
});
document.getElementById('addNote').addEventListener('click', function() {
const note = document.getElementById('note').value;
const duration = parseFloat(document.getElementById('duration').value);
melody.push({ frequency: parseFloat(note), duration: duration });
const noteName = document.getElementById('note').options[document.getElementById('note').selectedIndex].text;
document.getElementById('melodyOutput').innerHTML += `<p>Added: ${noteName} - ${duration}s</p>`;
});
document.getElementById('playMelody').addEventListener('click', async function() {
const volume = parseFloat(document.getElementById('volume').value);
for (let note of melody) {
await playTone(note.frequency, note.duration, volume);
}
});
function playTone(frequency, duration, volume) {
return new Promise((resolve) => {
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.type = 'square';
oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
gainNode.gain.setValueAtTime(volume, audioContext.currentTime);
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + duration);
oscillator.onended = resolve;
});
}
</script>
</body>
</html>
マウスオーバーでピロピロ鳴るやつ
%%html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Melody Generator</title>
<style>
.note-container {
display: flex;
flex-wrap: wrap;
}
.note {
padding: 10px;
margin: 0 0 30px 0; /* 上下の行間を10pxに設定 */
background-color: #f0f0f0;
width: 20px;
border: 1px solid #ccc;
cursor: pointer;
}
.note:hover {
background-color: #e0e0e0;
}
.melody-note {
display: flex;
align-items: center;
margin-bottom: 5px;
}
.melody-note button {
margin-left: 10px;
}
#melodyOutput > div {
display: flex;
flex-direction: column;
}
</style>
</head>
<body>
<h1>Melody Generator</h1>
<button id="toggleMode">Switch to Mouse Over Mode</button>
<label for="duration">Duration (s):</label>
<input type="range" id="duration" min="0.1" max="2.0" step="0.1" value="0.5">
<span id="durationValue">0.5</span>
<label for="volume">Volume:</label>
<input type="range" id="volume" min="0.0" max="1.0" step="0.1" value="0.5">
<span id="volumeValue">0.5</span>
<button id="playMelody">Play Melody</button>
<div class="note-container" id="noteContainer"></div>
<div id="melodyOutput"></div>
<script>
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
let melody = [];
let mode = 'mouseover';
let action = 'play';
const notes = [
{ name: 'C0 (ド)', freq: 16.35 }, { name: 'C#0/Db0 (ド#)', freq: 17.32 }, { name: 'D0 (レ)', freq: 18.35 }, { name: 'D#0/Eb0 (レ#)', freq: 19.45 }, { name: 'E0 (ミ)', freq: 20.60 },
{ name: 'F0 (ファ)', freq: 21.83 }, { name: 'F#0/Gb0 (ファ#)', freq: 23.12 }, { name: 'G0 (ソ)', freq: 24.50 }, { name: 'G#0/Ab0 (ソ#)', freq: 25.96 }, { name: 'A0 (ラ)', freq: 27.50 },
{ name: 'A#0/Bb0 (ラ#)', freq: 29.14 }, { name: 'B0 (シ)', freq: 30.87 }, { name: 'C1 (ド)', freq: 32.70 }, { name: 'C#1/Db1 (ド#)', freq: 34.65 }, { name: 'D1 (レ)', freq: 36.71 },
{ name: 'D#1/Eb1 (レ#)', freq: 38.89 }, { name: 'E1 (ミ)', freq: 41.20 }, { name: 'F1 (ファ)', freq: 43.65 }, { name: 'F#1/Gb1 (ファ#)', freq: 46.25 }, { name: 'G1 (ソ)', freq: 49.00 },
{ name: 'G#1/Ab1 (ソ#)', freq: 51.91 }, { name: 'A1 (ラ)', freq: 55.00 }, { name: 'A#1/Bb1 (ラ#)', freq: 58.27 }, { name: 'B1 (シ)', freq: 61.74 }, { name: 'C2 (ド)', freq: 65.41 },
{ name: 'C#2/Db2 (ド#)', freq: 69.30 }, { name: 'D2 (レ)', freq: 73.42 }, { name: 'D#2/Eb2 (レ#)', freq: 77.78 }, { name: 'E2 (ミ)', freq: 82.41 }, { name: 'F2 (ファ)', freq: 87.31 },
{ name: 'F#2/Gb2 (ファ#)', freq: 92.50 }, { name: 'G2 (ソ)', freq: 98.00 }, { name: 'G#2/Ab2 (ソ#)', freq: 103.83 }, { name: 'A2 (ラ)', freq: 110.00 }, { name: 'A#2/Bb2 (ラ#)', freq: 116.54 },
{ name: 'B2 (シ)', freq: 123.47 }, { name: 'C3 (ド)', freq: 130.81 }, { name: 'C#3/Db3 (ド#)', freq: 138.59 }, { name: 'D3 (レ)', freq: 146.83 }, { name: 'D#3/Eb3 (レ#)', freq: 155.56 },
{ name: 'E3 (ミ)', freq: 164.81 }, { name: 'F3 (ファ)', freq: 174.61 }, { name: 'F#3/Gb3 (ファ#)', freq: 185.00 }, { name: 'G3 (ソ)', freq: 196.00 }, { name: 'G#3/Ab3 (ソ#)', freq: 207.65 },
{ name: 'A3 (ラ)', freq: 220.00 }, { name: 'A#3/Bb3 (ラ#)', freq: 233.08 }, { name: 'B3 (シ)', freq: 246.94 }, { name: 'C4 (ド)', freq: 261.63 }, { name: 'C#4/Db4 (ド#)', freq: 277.18 },
{ name: 'D4 (レ)', freq: 293.66 }, { name: 'D#4/Eb4 (レ#)', freq: 311.13 }, { name: 'E4 (ミ)', freq: 329.63 }, { name: 'F4 (ファ)', freq: 349.23 }, { name: 'F#4/Gb4 (ファ#)', freq: 369.99 },
{ name: 'G4 (ソ)', freq: 392.00 }, { name: 'G#4/Ab4 (ソ#)', freq: 415.30 }, { name: 'A4 (ラ)', freq: 440.00 }, { name: 'A#4/Bb4 (ラ#)', freq: 466.16 }, { name: 'B4 (シ)', freq: 493.88 },
{ name: 'C5 (ド)', freq: 523.25 }, { name: 'C#5/Db5 (ド#)', freq: 554.37 }, { name: 'D5 (レ)', freq: 587.33 }, { name: 'D#5/Eb5 (レ#)', freq: 622.25 }, { name: 'E5 (ミ)', freq: 659.25 },
{ name: 'F5 (ファ)', freq: 698.46 }, { name: 'F#5/Gb5 (ファ#)', freq: 739.99 }, { name: 'G5 (ソ)', freq: 783.99 }, { name: 'G#5/Ab5 (ソ#)', freq: 830.61 }, { name: 'A5 (ラ)', freq: 880.00 },
{ name: 'A#5/Bb5 (ラ#)', freq: 932.33 }, { name: 'B5 (シ)', freq: 987.77 }, { name: 'C6 (ド)', freq: 1046.50 }, { name: 'C#6/Db6 (ド#)', freq: 1108.73 }, { name: 'D6 (レ)', freq: 1174.66 },
{ name: 'D#6/Eb6 (レ#)', freq: 1244.51 }, { name: 'E6 (ミ)', freq: 1318.51 }, { name: 'F6 (ファ)', freq: 1396.91 }, { name: 'F#6/Gb6 (ファ#)', freq: 1479.98 }, { name: 'G6 (ソ)', freq: 1567.98 },
{ name: 'G#6/Ab6 (ソ#)', freq: 1661.22 }, { name: 'A6 (ラ)', freq: 1760.00 }, { name: 'A#6/Bb6 (ラ#)', freq: 1864.66 }, { name: 'B6 (シ)', freq: 1975.53 }, { name: 'C7 (ド)', freq: 2093.00 },
{ name: 'C#7/Db7 (ド#)', freq: 2217.46 }, { name: 'D7 (レ)', freq: 2349.32 }, { name: 'D#7/Eb7 (レ#)', freq: 2489.02 }, { name: 'E7 (ミ)', freq: 2637.02 }, { name: 'F7 (ファ)', freq: 2793.83 },
{ name: 'F#7/Gb7 (ファ#)', freq: 2959.96 }, { name: 'G7 (ソ)', freq: 3135.96 }, { name: 'G#7/Ab7 (ソ#)', freq: 3322.44 }, { name: 'A7 (ラ)', freq: 3520.00 }, { name: 'A#7/Bb7 (ラ#)', freq: 3729.31 },
{ name: 'B7 (シ)', freq: 3951.07 }, { name: 'C8 (ド)', freq: 4186.01 }
];
function createNoteDiv(note) {
const div = document.createElement('div');
div.className = 'note';
div.textContent = note.name;
div.dataset.freq = note.freq;
if (mode === 'click') {
div.addEventListener('click', handleNoteClick);
} else if (mode === 'mouseover') {
div.addEventListener('mouseover', handleNoteMouseOver);
} else if (mode === 'add') {
div.addEventListener('click', handleNoteAdd);
}
return div;
}
function updateNoteDivs() {
const container = document.getElementById('noteContainer');
container.innerHTML = '';
notes.forEach(note => {
container.appendChild(createNoteDiv(note));
});
}
document.getElementById('toggleMode').addEventListener('click', function() {
if (mode === 'mouseover') {
mode = 'click';
this.textContent = 'Click Mode';
} else if (mode === 'click') {
mode = 'add';
this.textContent = 'Add Note Mode';
} else if (mode === 'add') {
mode = 'mouseover';
this.textContent = 'Mouseover Mode';
}
updateNoteDivs(); // モード変更後にupdateNoteDivsを呼び出して正しいリスナーを設定する
});
document.getElementById('duration').addEventListener('input', function() {
document.getElementById('durationValue').textContent = this.value;
});
document.getElementById('volume').addEventListener('input', function() {
document.getElementById('volumeValue').textContent = this.value;
});
document.getElementById('playMelody').addEventListener('click', async function() {
for (let note of melody) {
await playTone(note.frequency, note.duration, note.volume);
}
});
function handleNoteClick(event) {
const freq = parseFloat(event.target.dataset.freq);
const duration = parseFloat(document.getElementById('duration').value);
const volume = parseFloat(document.getElementById('volume').value);
playTone(freq, duration, volume);
}
function handleNoteMouseOver(event) {
const freq = parseFloat(event.target.dataset.freq);
const duration = parseFloat(document.getElementById('duration').value);
const volume = parseFloat(document.getElementById('volume').value);
playTone(freq, duration, volume);
}
function handleNoteAdd(event) {
const noteName = event.target.textContent;
const frequency = parseFloat(event.target.dataset.freq);
const duration = parseFloat(document.getElementById('duration').value);
const volume = parseFloat(document.getElementById('volume').value);
melody.push({ name: noteName, frequency, duration, volume });
updateMelodyOutput();
}
function updateMelodyOutput() {
const container = document.getElementById('melodyOutput');
container.innerHTML = '';
melody.forEach((note, index) => {
const div = document.createElement('div');
div.className = 'melody-note';
div.textContent = `${note.name} - ${note.duration}s - Volume: ${note.volume}`;
const deleteButton = document.createElement('button');
deleteButton.textContent = 'Delete';
deleteButton.addEventListener('click', () => {
melody.splice(index, 1);
updateMelodyOutput();
});
div.appendChild(deleteButton);
container.appendChild(div);
});
}
function playTone(frequency, duration, volume) {
return new Promise((resolve) => {
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.type = 'square';
oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
gainNode.gain.setValueAtTime(volume, audioContext.currentTime);
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + duration);
oscillator.onended = resolve;
});
}
updateNoteDivs();
</script>
</body>
</html>
この記事が気に入ったらサポートをしてみませんか?