mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Add five hardware lessons on sampling and quantizing sound.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
7f989691a2
commit
9860c56329
7 changed files with 420 additions and 5 deletions
351
src/hw.c
351
src/hw.c
|
|
@ -7,6 +7,11 @@ NetLesson hw_lessons[HW_LESSONS] = {
|
|||
{ .n_slides = HW2_SLIDES, .unit_page = "hwunit2", .ex_page = "hwex2" },
|
||||
{ .n_slides = HW3_SLIDES, .unit_page = "hwunit3", .ex_page = "hwex3" },
|
||||
{ .n_slides = HW4_SLIDES, .unit_page = "hwunit4", .ex_page = "hwex4" },
|
||||
{ .n_slides = HW5_SLIDES, .unit_page = "hwunit5", .ex_page = "hwex5" },
|
||||
{ .n_slides = HW6_SLIDES, .unit_page = "hwunit6", .ex_page = "hwex6" },
|
||||
{ .n_slides = HW7_SLIDES, .unit_page = "hwunit7", .ex_page = "hwex7" },
|
||||
{ .n_slides = HW8_SLIDES, .unit_page = "hwunit8", .ex_page = "hwex8" },
|
||||
{ .n_slides = HW9_SLIDES, .unit_page = "hwunit9", .ex_page = "hwex9" },
|
||||
};
|
||||
|
||||
void hw_rail_theme_reset(void);
|
||||
|
|
@ -253,7 +258,8 @@ void hw_add_node(GtkFixed *fixed, int index) {
|
|||
GtkWidget *name;
|
||||
char *text;
|
||||
static const char *unit_keys[HW_LESSONS] = {
|
||||
"hw_unit1", "hw_unit2", "hw_unit3", "hw_unit4"
|
||||
"hw_unit1", "hw_unit2", "hw_unit3", "hw_unit4",
|
||||
"hw_unit5", "hw_unit6", "hw_unit7", "hw_unit8", "hw_unit9"
|
||||
};
|
||||
|
||||
card = gtk_button_new();
|
||||
|
|
@ -979,3 +985,346 @@ GtkWidget *build_hw_unit4_exercise_page(void) {
|
|||
return build_hw_mcq_page(3, "hwunit4", "hw_ex4_title", "hw_quiz4_head",
|
||||
qs, hints, 4);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit5_page(void) {
|
||||
static const NetSlide slides[HW5_SLIDES] = {
|
||||
{
|
||||
"1 / 2 • Signál", "Analogový a digitální zvuk",
|
||||
"Tip: analog je spojitý, digitál je posloupnost čísel.",
|
||||
{
|
||||
"Analogový zvuk je spojitý signál – v každém okamžiku "
|
||||
"má nějakou hodnotu.",
|
||||
"Digitální zvuk je posloupnost čísel, která ten signál "
|
||||
"popisují.",
|
||||
"Z mikrofonu vychází analogové napětí, do reproduktoru "
|
||||
"musí zase jít spojitý signál.",
|
||||
"Počítač umí uložit jen čísla, proto se zvuk digitalizuje.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
"2 / 2 • Převod", "A/D a D/A převodník",
|
||||
"Tip: ADC dovnitř, DAC ven. Digitalizace = vzorkování + kvantování.",
|
||||
{
|
||||
"A/D převodník (ADC) převede analogový signál na čísla.",
|
||||
"D/A převodník (DAC) z čísel znovu složí spojitý signál.",
|
||||
"Digitalizace má dva kroky: vzorkování a kvantování.",
|
||||
"Vzorkování určí, kdy se hodnota změří.",
|
||||
"Kvantování určí, na kolik hladin se amplituda zaokrouhlí.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return build_hw_unit_page(&hw_lessons[4], "hw_unit5", "hw_unit5_sub",
|
||||
slides, HW5_SLIDES);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit5_exercise_page(void) {
|
||||
static const ChoiceQ qs[] = {
|
||||
{"Co je analogový zvuk?",
|
||||
{"Posloupnost celých čísel",
|
||||
"Spojitý signál s hodnotou v každém okamžiku",
|
||||
"Jen název souboru WAV",
|
||||
"Jen bit v paměti"},
|
||||
4, 1},
|
||||
{"Co dělá A/D převodník (ADC)?",
|
||||
{"Převádí analogový signál na čísla",
|
||||
"Zesiluje jen reproduktor",
|
||||
"Maže vysoké tóny po uložení",
|
||||
"Počítá jen velikost souboru"},
|
||||
4, 0},
|
||||
{"Jaké jsou dva hlavní kroky digitalizace zvuku?",
|
||||
{"Komprese a tisk",
|
||||
"Vzorkování a kvantování",
|
||||
"Šifrování a záloha",
|
||||
"Násobení a dělení"},
|
||||
4, 1},
|
||||
{"Co dělá D/A převodník (DAC)?",
|
||||
{"Z čísel znovu skládá spojitý signál",
|
||||
"Měří jen vzorkovací frekvenci",
|
||||
"Ukládá zvuk jako text",
|
||||
"Zvyšuje počet bitů v souboru"},
|
||||
4, 0},
|
||||
};
|
||||
static const char *hints[] = {
|
||||
"Analog = spojitý signál",
|
||||
"ADC převádí analog na čísla",
|
||||
"Digitalizace = vzorkování + kvantování",
|
||||
"DAC skládá z čísel spojitý signál",
|
||||
};
|
||||
return build_hw_mcq_page(4, "hwunit5", "hw_ex5_title", "hw_quiz5_head",
|
||||
qs, hints, 4);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit6_page(void) {
|
||||
static const NetSlide slides[HW6_SLIDES] = {
|
||||
{
|
||||
"1 / 2 • Vzorky", "Vzorkování",
|
||||
"Tip: vzorkovací frekvence fs = počet vzorků za sekundu (Hz).",
|
||||
{
|
||||
"Vzorkování měří velikost signálu v pravidelných "
|
||||
"okamžicích.",
|
||||
"Mezi vzorky se hodnota neukládá.",
|
||||
"Vzorkovací frekvence fs je počet vzorků za sekundu.",
|
||||
"Jednotka je hertz (Hz). 1 kHz = 1000 vzorků za sekundu.",
|
||||
"Vyšší fs zachytí rychlejší změny, tedy vyšší tóny.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
"2 / 2 • Nyquist", "Nyquistův–Shannonův teorém",
|
||||
"Tip: fs musí být vyšší než 2 × fmax. Nyquistova frekvence je fs / 2.",
|
||||
{
|
||||
"Pro věrnou rekonstrukci musí být fs vyšší než dvojnásobek "
|
||||
"nejvyšší frekvence ve signálu.",
|
||||
"Nyquistova frekvence je fs / 2 – vyšší tón už záznam neunese.",
|
||||
"Člověk slyší zhruba do 20 kHz, dvojnásobek je 40 kHz.",
|
||||
"CD proto používá 44,1 kHz: o něco víc než 40 kHz, "
|
||||
"aby zbyl prostor pro filtr.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return build_hw_unit_page(&hw_lessons[5], "hw_unit6", "hw_unit6_sub",
|
||||
slides, HW6_SLIDES);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit6_exercise_page(void) {
|
||||
static const ChoiceQ qs[] = {
|
||||
{"Co je vzorkovací frekvence?",
|
||||
{"Počet bitů v jednom vzorku",
|
||||
"Počet vzorků za sekundu",
|
||||
"Délka skladby v minutách",
|
||||
"Počet kanálů (mono nebo stereo)"},
|
||||
4, 1},
|
||||
{"V jakých jednotkách se udává vzorkovací frekvence?",
|
||||
{"V bytech", "V hertzech", "Ve voltech", "V pixelech"},
|
||||
4, 1},
|
||||
{"Co říká Nyquistův–Shannonův teorém?",
|
||||
{"fs musí být vyšší než dvojnásobek nejvyšší frekvence",
|
||||
"fs musí být vždy 8 kHz",
|
||||
"Stačí jeden vzorek na celou skladbu",
|
||||
"Bitová hloubka musí být 1"},
|
||||
4, 0},
|
||||
{"Proč má audio CD vzorkovací frekvenci 44,1 kHz?",
|
||||
{"Protože byte má 8 bitů",
|
||||
"Sluch sahá asi do 20 kHz a fs musí být vyšší než dvojnásobek",
|
||||
"Protože stereo má dva kanály",
|
||||
"Protože minutu tvoří 60 sekund"},
|
||||
4, 1},
|
||||
};
|
||||
static const char *hints[] = {
|
||||
"fs = počet vzorků za sekundu",
|
||||
"Jednotka vzorkovací frekvence je hertz",
|
||||
"fs > 2 × fmax",
|
||||
"20 kHz × 2 = 40 kHz, CD má 44,1 kHz",
|
||||
};
|
||||
return build_hw_mcq_page(5, "hwunit6", "hw_ex6_title", "hw_quiz6_head",
|
||||
qs, hints, 4);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit7_page(void) {
|
||||
static const NetSlide slides[HW7_SLIDES] = {
|
||||
{
|
||||
"1 / 2 • Hladiny", "Kvantování",
|
||||
"Tip: n bitů → 2ⁿ hladin. 8 bitů = 256, 16 bitů = 65 536.",
|
||||
{
|
||||
"Kvantování zaokrouhlí amplitudu každého vzorku "
|
||||
"na nejbližší z konečného počtu hladin.",
|
||||
"Počet hladin je 2ⁿ, kde n je bitová hloubka "
|
||||
"(počet bitů na vzorek).",
|
||||
"8 bitů dává 256 hladin, 16 bitů dává 65 536 hladin.",
|
||||
"Vzorkování říká jak často, kvantování jak přesně.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
"2 / 2 • Chyba", "Kvantizační chyba",
|
||||
"Tip: víc bitů = jemnější hladiny, menší šum a větší soubor.",
|
||||
{
|
||||
"Kvantizační chyba je rozdíl mezi skutečnou hodnotou "
|
||||
"a zvolenou hladinou.",
|
||||
"V záznamu se projeví jako kvantizační šum.",
|
||||
"Větší bitová hloubka hladiny zjemní a šum zmenší.",
|
||||
"Audio CD používá 16 bitů na vzorek, studio často 24 bitů.",
|
||||
"Vyšší hloubka také zvětší datový tok.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return build_hw_unit_page(&hw_lessons[6], "hw_unit7", "hw_unit7_sub",
|
||||
slides, HW7_SLIDES);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit7_exercise_page(void) {
|
||||
static const ChoiceQ qs[] = {
|
||||
{"Co je kvantování?",
|
||||
{"Měření signálu v pravidelných okamžicích",
|
||||
"Zaokrouhlení amplitudy na konečný počet hladin",
|
||||
"Převod čísel zpět na analog",
|
||||
"Komprese souboru MP3"},
|
||||
4, 1},
|
||||
{"Kolik hladin má 8bitové kvantování?",
|
||||
{"8", "16", "256", "65 536"},
|
||||
4, 2},
|
||||
{"Kolik hladin má 16bitové kvantování?",
|
||||
{"16", "256", "1 024", "65 536"},
|
||||
4, 3},
|
||||
{"Co je kvantizační chyba?",
|
||||
{"Rozdíl mezi skutečnou hodnotou a zvolenou hladinou",
|
||||
"Příliš nízká vzorkovací frekvence",
|
||||
"Počet kanálů ve stereu",
|
||||
"Délka skladby v sekundách"},
|
||||
4, 0},
|
||||
};
|
||||
static const char *hints[] = {
|
||||
"Kvantování zaokrouhluje amplitudu na hladiny",
|
||||
"8 bitů → 2⁸ = 256 hladin",
|
||||
"16 bitů → 2¹⁶ = 65 536 hladin",
|
||||
"Kvantizační chyba = rozdíl proti skutečné hodnotě",
|
||||
};
|
||||
return build_hw_mcq_page(6, "hwunit7", "hw_ex7_title", "hw_quiz7_head",
|
||||
qs, hints, 4);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit8_page(void) {
|
||||
static const NetSlide slides[HW8_SLIDES] = {
|
||||
{
|
||||
"1 / 2 • PCM", "Pulzně kódová modulace",
|
||||
"Tip: tok = fs × bity na vzorek × počet kanálů.",
|
||||
{
|
||||
"PCM uloží každý vzorek jako binární číslo.",
|
||||
"Je to základní nekomprimovaný záznam (WAV, audio CD).",
|
||||
"Datový tok = vzorkovací frekvence × bitová hloubka "
|
||||
"× počet kanálů.",
|
||||
"Mono má jeden kanál, stereo dva (levý a pravý).",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
"2 / 2 • Velikost", "Kolik dat zabere CD",
|
||||
"Tip: komprese (MP3, AAC) soubor zmenší, ale část informace zahodí.",
|
||||
{
|
||||
"CD stereo: 44 100 Hz × 16 bit × 2 = 1 411 200 bit/s.",
|
||||
"To je 176 400 B/s.",
|
||||
"Za minutu je to 10 584 000 B, tedy přes 10 MB.",
|
||||
"Delší záznam, vyšší fs, více bitů nebo více kanálů "
|
||||
"soubor zvětší.",
|
||||
"MP3 a AAC soubor zmenší za cenu ztráty části informace.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return build_hw_unit_page(&hw_lessons[7], "hw_unit8", "hw_unit8_sub",
|
||||
slides, HW8_SLIDES);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit8_exercise_page(void) {
|
||||
static const ChoiceQ qs[] = {
|
||||
{"Co je PCM?",
|
||||
{"Každý vzorek uložený jako binární číslo",
|
||||
"Jen komprimovaný formát MP3",
|
||||
"Filtr před mikrofonem",
|
||||
"Jednotka hlasitosti"},
|
||||
4, 0},
|
||||
{"Jak se spočítá datový tok nekomprimovaného zvuku?",
|
||||
{"fs + bity + kanály",
|
||||
"fs × bitová hloubka × počet kanálů",
|
||||
"jen délka skladby v minutách",
|
||||
"počet hladin děleno dvěma"},
|
||||
4, 1},
|
||||
{"Jaký je datový tok audio CD ve stereu?",
|
||||
{"44 100 bit/s", "256 bit/s", "1 411 200 bit/s", "8 bit/s"},
|
||||
4, 2},
|
||||
{"Co udělá komprese MP3 se záznamem?",
|
||||
{"Zvětší soubor a přidá vzorky",
|
||||
"Zmenší soubor a část informace zahodí",
|
||||
"Změní jen název souboru",
|
||||
"Převede digitál zpět na analog"},
|
||||
4, 1},
|
||||
};
|
||||
static const char *hints[] = {
|
||||
"PCM = vzorek jako binární číslo",
|
||||
"tok = fs × bity × kanály",
|
||||
"44 100 × 16 × 2 = 1 411 200 bit/s",
|
||||
"MP3 soubor zmenší a část informace zahodí",
|
||||
};
|
||||
return build_hw_mcq_page(7, "hwunit8", "hw_ex8_title", "hw_quiz8_head",
|
||||
qs, hints, 4);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit9_page(void) {
|
||||
static const NetSlide slides[HW9_SLIDES] = {
|
||||
{
|
||||
"1 / 2 • Aliasing", "Když je vzorkování moc řídké",
|
||||
"Tip: aliasing vznikne před uložením a z hotových vzorků "
|
||||
"už nejde spolehlivě odstranit.",
|
||||
{
|
||||
"Aliasing vznikne, když je fs příliš nízká a poruší se "
|
||||
"Nyquistovo pravidlo.",
|
||||
"Vysoká frekvence se v záznamu jeví jako nižší tón.",
|
||||
"Příklad: tón 6 kHz vzorkovaný 8 kHz se jeví jako 2 kHz.",
|
||||
"Antialiasingový filtr před převodníkem vysoké frekvence "
|
||||
"ořízne.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
"2 / 2 • Formáty", "Běžné parametry záznamu",
|
||||
"Tip: vyšší fs a víc bitů znamená věrnější záznam a větší tok.",
|
||||
{
|
||||
"Audio CD: 44,1 kHz, 16 bitů, stereo.",
|
||||
"Klasický telefonní hovor: 8 kHz a 8 bitů – řeč se vejde "
|
||||
"do pásma do 4 kHz.",
|
||||
"Studio často používá 48 nebo 96 kHz a 24 bitů.",
|
||||
"Parametry se volí podle toho, co má záznam unést "
|
||||
"a jak velký smí být.",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return build_hw_unit_page(&hw_lessons[8], "hw_unit9", "hw_unit9_sub",
|
||||
slides, HW9_SLIDES);
|
||||
}
|
||||
|
||||
GtkWidget *build_hw_unit9_exercise_page(void) {
|
||||
static const ChoiceQ qs[] = {
|
||||
{"Kdy vzniká aliasing?",
|
||||
{"Když je vzorkovací frekvence příliš nízká",
|
||||
"Když má záznam 24 bitů",
|
||||
"Když je soubor ve stereu",
|
||||
"Když se použije D/A převodník"},
|
||||
4, 0},
|
||||
{"K čemu je antialiasingový filtr?",
|
||||
{"Zvětší bitovou hloubku po uložení",
|
||||
"Před vzorkováním ořízne frekvence nad Nyquistovu",
|
||||
"Spočítá datový tok",
|
||||
"Převede mono na stereo"},
|
||||
4, 1},
|
||||
{"Jaké parametry má audio CD?",
|
||||
{"8 kHz, 8 bitů, mono",
|
||||
"44,1 kHz, 16 bitů, stereo",
|
||||
"96 kHz, 8 bitů, mono",
|
||||
"1 kHz, 1 bit, stereo"},
|
||||
4, 1},
|
||||
{"Proč telefonnímu hovoru stačí vzorkování 8 kHz?",
|
||||
{"Řeč se vejde do pásma zhruba do 4 kHz",
|
||||
"Telefon nahrává na audio CD",
|
||||
"8 kHz je totéž co 44,1 kHz",
|
||||
"Řeč nemá žádnou frekvenci"},
|
||||
4, 0},
|
||||
};
|
||||
static const char *hints[] = {
|
||||
"Aliasing = příliš nízká fs",
|
||||
"Filtr ořízne frekvence nad fs / 2 ještě před vzorkováním",
|
||||
"CD = 44,1 kHz, 16 bit, stereo",
|
||||
"Pásmo řeči je do asi 4 kHz, proto stačí fs = 8 kHz",
|
||||
};
|
||||
return build_hw_mcq_page(8, "hwunit9", "hw_ex9_title", "hw_quiz9_head",
|
||||
qs, hints, 4);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue