-
Notifications
You must be signed in to change notification settings - Fork 0
/
Rust15.html
730 lines (518 loc) · 168 KB
/
Rust15.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- iOS Safari -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- Chrome, Firefox OS and Opera Status Bar Color -->
<meta name="theme-color" content="#FFFFFF">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css">
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.19.0/themes/prism.min.css">
<link rel="stylesheet" type="text/css" href="css/SourceSansPro.css">
<link rel="stylesheet" type="text/css" href="css/theme.css">
<link rel="stylesheet" type="text/css" href="css/notablog.css">
<link rel="stylesheet" type="text/css" href="css/CustomSetting.css">
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🥥</text></svg>">
<style>
:root {
font-size: 20px;
}
</style>
<title>Rust 驱动 Audio - 播放和录音 | 413’s Website</title>
<meta property="og:type" content="blog">
<meta property="og:title" content="Rust 驱动 Audio - 播放和录音">
<meta name="description" content="PCM DAC ADC">
<meta property="og:description" content="PCM DAC ADC">
<meta property="og:image" content="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🦀</text></svg>">
<style>
.DateTagBar {
margin-top: 1.0rem;
}
</style>
</head>
<body>
<nav class="Navbar">
<a href="index.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🥥</text></svg>"></span>
<span>Home</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="blog-collection.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🥅</text></svg>"></span>
<span>blog mark</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="Note.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🎶</text></svg>"></span>
<span>Note</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="reference.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>😷</text></svg>"></span>
<span>杂项</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="About.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>😀</text></svg>"></span>
<span>About</span>
</div>
</a>
</nav>
<header class="Header">
<div class="Header__Spacer Header__Spacer--NoCover">
</div>
<div class="Header__Icon">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🦀</text></svg>"></span>
</div>
<h1 class="Header__Title">Rust 驱动 Audio - 播放和录音</h1>
<div class="DateTagBar">
<span class="DateTagBar__Item DateTagBar__Date">Posted on Mon, Sep 2, 2024</span>
<span class="DateTagBar__Item DateTagBar__Tag DateTagBar__Tag--purple">
<a href="tag/Rust.html">Rust</a>
</span>
<span class="DateTagBar__Item DateTagBar__Tag DateTagBar__Tag--red">
<a href="tag/单片机.html">单片机</a>
</span>
</div>
</header>
<div id="content-html"></div>
<article id="https://www.notion.so/67b96478fd6243d0be7f914c00762c01" class="PageRoot PageRoot--FullWidth"><h2 id="https://www.notion.so/609d73b80c684fbeb23fd76032cfb034" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/609d73b80c684fbeb23fd76032cfb034"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">1 音频格式 </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-audio/#%E9%9F%B3%E9%A2%91%E6%A0%BC%E5%BC%8F"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/1b063db9fdd6438d8f328919b4eff538" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">PCM:脉冲编码调制(英语:Pulse-code modulation,缩写:PCM)是一种模拟信号的数字化方法。 A PCM stream has two basic properties that determine the stream’s fidelity to the original analog signal:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/8e84c85ed44a46da96186b72c9a4adc8" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">the sampling rate</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, which is the number of times per second that samples are taken;</mark></span></span></li><li id="https://www.notion.so/0d1762d488014d9485671bdc536bd1ba" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">and </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">the bit depth</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, which determines the number of possible digital values that can be used to represent each sample.</mark></span></span></li></ol><div id="https://www.notion.so/0e6b488440c24b5fa91d882a1c150420" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">The compact disc (CD) brought PCM to consumer audio applications with its introduction in 1982. The CD uses </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">a 44,100 Hz sampling frequency and 16-bit resolution</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> and stores up to 80 minutes of stereo audio per disc. stereo audio 是通过 two-channel 提供的。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/a5cf3d72ba9e4f11bbbc8ca8bfeb4d55" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">The audio contained in a CD-DA consists of </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">two-channel signed 16-bit LPCM sampled at 44,100 Hz</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> and written as a little-endian interleaved stream with left channel coming first</mark></span></span></li></ul><div id="https://www.notion.so/d807c89875344efa9ca91b4f755bb59c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 的解释:</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Linear pulse-code modulation (LPCM)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 是一种数字信号的表示方法,主要用于音频信号。它通过将模拟信号定期采样并量化为线性级别的数字值来工作。LPCM是脉冲编码调制(PCM)的一种形式,特别强调了量化过程是线性的。这意味着模拟信号的每个采样值都直接转换成相应的数字值, 而这个转换过程不涉及任何非线性压缩 。LPCM的关键步骤包括采样、量化和编码:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/db54e0538d6845479bf3b3a1b22f5308" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">采样</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">:这是将连续的模拟信号转换为离散信号的过程。根据奈奎斯特定理,为了避免混叠效应,采样频率应至少为信号最高频率的两倍。例如,CD音频以</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">44.1kHz</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">的频率采样,这意味着它可以准确地再现高达</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">22.05kHz </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">的声音频率,覆盖了人耳可听范围。</mark></span></span></li><li id="https://www.notion.so/9a390944ea63408a83c10b437eb42883" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">量化</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">:量化过程涉及将每个采样点的振幅(即大小或强度)近似到一组有限的数值中。在LPCM中,这个过程是线性的,这意味着模拟信号的动态范围被均匀分配给量化级别。量化的精度通常用比特数表示,比如CD音质的LPCM采用16位量化,提供了65536(2^16)个不同的可能振幅级别。</mark></span></span></li><li id="https://www.notion.so/c999a01d3dcd4cc0896c9e67d4e6116b" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">编码</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">:最后,量化后的数值被编码为数字信号,可以存储或传输。在LPCM中,这些数值直接表示信号的振幅, 不进行任何额外的压缩或编码 。</mark></span></span></li></ol><div id="https://www.notion.so/a4c289f383c04e889a0cea38a6e19838" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">是一种无损的音频格式 ,因为它不涉及压缩过程中的信息丢失(尽管原始模拟信号在采样和量化过程中可能会有一定程度的近似)。由于它的这个特性, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">广泛用于需要高音质的应用中 ,如CD音频、DVD音频、蓝光音频和一些专业音频录制系统。</mark></span></span></p></div><div id="https://www.notion.so/00ade2ff30234e6194dcea269d8e76e5" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">的主要优点包括简单、直接和高质量的音频表示, 但它也有一个缺点,即相对较高的数据率 。例如,未压缩的CD质量音频(使用44.1kHz的采样率和</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">16</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">位深度的立体声</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">)的数据率约为</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">1.4Mbps</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">。相比之下, 许多现代音频压缩技术,如</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MP3</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">或</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">AAC</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,通过去除人耳难以察觉的音频信息来大幅度减少所需的数据率,但这种压缩是有损的。</mark></span></span></p></div><div id="https://www.notion.so/02de234d5a344aeb8716ba22a9f838fa" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">立体声和多声道 LPCM:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/3d214b749c874972b09fcf35cb8fc7c7" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">在立体声 LPCM 流中,左声道和右声道的采样值通常是 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">交错存储的</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 。例如,一个典型的存储序列可能是L1、 R1、L2、R2、…、Ln、Rn,其中L和R分别代表左声道和右声道的采样值,n是采样点的索引。</mark></span></span></li><li id="https://www.notion.so/2390b02328214c86a9a6c504465cff64" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">在多声道LPCM流中,各声道的采样值可以按不同方式组织。最常见的是交错方式,即按照采样时刻顺序依次存储各声道的采样值,比如L1、C1、R1、LS1、RS1、L2、C2、R2、LS2、RS2、…,其中L、C、R、LS、RS分别代表左前、中央、右前、左后和右后声道的采样值。</mark></span></span></li></ol><div id="https://www.notion.so/878d9f7d329a4fca9b8249e357f041a4" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">参考:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://planethifi.com/pcm-audio/"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://planethifi.com/pcm-audio/</mark></a></span></span></p></div><div id="https://www.notion.so/f928e51672fc4a30b5f8f0d5590df015" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorPink"><code class="SemanticString__Fragment SemanticString__Fragment--Code">WAV(Waveform Audio File Format)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 是一种音频文件格式,它通常用来 存储未压缩的音频数据 ,这些数据大多数情况下 使用</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorPink"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Linear Pulse-Code Modulation (LPCM) </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">编码 。WAV格式由微软和IBM开发,最初是为Windows 3.1 操作系统设计的。由于其无损特性和广泛的兼容性,WAV格式成为了保存高质量音频的一种流行选择。</mark></span></span></p></div><div id="https://www.notion.so/846480aabb274570ab64a0234c47af44" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">总结:WAV 文件和 LPCM 的关系:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/d672134532cb492faa1fa3f5170aadef" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**存储LPCM数据**:WAV文件格式经常用来存储LPCM编码的音频数据。这意味着WAV文件可以 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">保存按照LPCM方法采样、量化和编码的音频信号,保留原始音频的所有细节而不会丢失任何信息</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 。</mark></span></span></li><li id="https://www.notion.so/1643b3a6bc2548828dd12bd7d8051db9" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**无损音频格式**:由于LPCM是一种无损编码方式, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">因此使用LPCM编码的WAV文件也是无损的</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 。这使得WAV文件特别适合需要高质量音频,如专业音乐制作、音频编辑和音频分析的场合。</mark></span></span></li><li id="https://www.notion.so/54e2875b4dd14d1aae20b7c75bf9d971" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**高数据率**:LPCM编码的音频数据未经过压缩,所以WAV文件通常具有较高的数据率。例如,一段标准的CD质量音频(44.1kHz采样率、16位深度、立体声)的数据率大约为1.4Mbps。 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">这意味着WAV文件可以变得相当大</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,尤其是对于较长的录音。</mark></span></span></li><li id="https://www.notion.so/84f47b7bd257457694f3eac1e34dee51" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**广泛的应用**:WAV格式由于其简单、无损和高质量的特性,在很多应用中被广泛使用,尤其是在需要原始音质的场合,如音乐制作、电影后期制作、广播和科学研究等。</mark></span></span></li></ul><h3 id="https://www.notion.so/9f6d1f9c15374a6d80615e2983f80670" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--3"><a class="Anchor" href="#https://www.notion.so/9f6d1f9c15374a6d80615e2983f80670"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">总结</mark></span></span></h3><div id="https://www.notion.so/9e9c499fc210495dbbe75743e4f58a08" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">文件不需要解码,可以直接读取 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM 编码数据</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,然后通过 I2S 接口发送给功放芯片播放。</mark></span></span></p></div><div id="https://www.notion.so/aa3429b6fe6e4555923aaa43a6b5f1c8" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/66fe97cab2fb44019af27155e34d277e" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span>// https://github.com/espressif/esp-box/blob/master/examples/watering_demo/main/app/app_audio.c
static void audio_beep_task(void *pvParam)
{
while (true) {
xSemaphoreTake(audio_sem, portMAX_DELAY);
b_audio_playing = true;
sr_echo_play("/spiffs/echo_en_wake.wav"); // 直接播放 wav 文件的音频数据
b_audio_playing = false;
/* It's useful if wake audio didn't finish playing when next wake word detetced */
// xSemaphoreTake(audio_sem, 0);
}
}
esp_err_t sr_echo_play(void *filepath)
{
FILE *fp = NULL;
struct stat file_stat;
esp_err_t ret = ESP_OK;
const size_t chunk_size = 4096;
uint8_t *buffer = malloc(chunk_size);
ESP_GOTO_ON_FALSE(NULL != buffer, ESP_FAIL, EXIT, TAG, "buffer malloc failed");
ESP_GOTO_ON_FALSE(-1 != stat(filepath, &file_stat), ESP_FAIL, EXIT, TAG, "Failed to stat file");
fp = fopen(filepath, "r");
ESP_GOTO_ON_FALSE(NULL != fp, ESP_FAIL, EXIT, TAG, "Failed create record file");
wav_header_t wav_head;
int len = fread(&wav_head, 1, sizeof(wav_header_t), fp);
ESP_GOTO_ON_FALSE(len > 0, ESP_FAIL, EXIT, TAG, "Read wav header failed");
if (NULL == strstr((char *)wav_head.Subchunk1ID, "fmt") &&
NULL == strstr((char *)wav_head.Subchunk2ID, "data")) {
ESP_LOGI(TAG, "PCM format");
fseek(fp, 0, SEEK_SET);
wav_head.SampleRate = 16000;
wav_head.NumChannels = 2;
wav_head.BitsPerSample = 16;
}
ESP_LOGD(TAG, "frame_rate= %" PRIi32 ", ch=%d, width=%d", wav_head.SampleRate, wav_head.NumChannels, wav_head.BitsPerSample);
bsp_codec_set_fs(wav_head.SampleRate, wav_head.BitsPerSample, I2S_SLOT_MODE_STEREO);
bsp_codec_mute_set(true);
bsp_codec_mute_set(false);
bsp_codec_volume_set(100, NULL);
size_t cnt, total_cnt = 0;
do {
/* Read file in chunks into the scratch buffer */
len = fread(buffer, 1, chunk_size, fp);
if (len <= 0) {
break;
} else if (le</span></span><span class="SemanticString"><span>n > 0) {
bsp_i2s_write(buffer, len, &cnt, portMAX_DELAY);
total_cnt += cnt;
}
} while (1);
ESP_LOGI(TAG, "play end, %d K", total_cnt / 1024);
EXIT:
if (fp) {
fclose(fp);
}
if (buffer) {
free(buffer);
}
return ret;
}</span></span></span></code></pre><div id="https://www.notion.so/0aec871ec60342b29c7fd70c28343463" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">There are three major groups of </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">audio file formats</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> :</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/12481e7949004ab583a5d9019d78ecb7" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Uncompressed audio formats, such as </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">WAV</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, AIFF, AU or raw header-less </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">; Note wav can also use compression as well.</mark></span></span></li><li id="https://www.notion.so/d73c811016e4493d8566a4b1490d2785" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Formats with lossless compression, such as </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">FLAC, Monkey's Audio (filename extension .ape)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, WavPack (filename extension .wv), TTA, ATRAC Advanced Lossless, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ALAC (filename extension .m4a, Apple Lossless)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, MPEG-4 SLS, MPEG-4 ALS, MPEG-4 DST, Windows Media Audio Lossless (WMA Lossless), and Shorten (SHN).</mark></span></span><ol class="NumberedListWrapper"><li id="https://www.notion.so/ba914d1999fc49e8923e3954a9ef9ab4" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Formats with lossy compression, such as Opus, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MP3</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, Vorbis, Musepack, AAC, ATRAC and Windows Media Audio Lossy (WMA lossy).</mark></span></span></li></ol></li></ol><div id="https://www.notion.so/4b26e243305d423fa145c29ebabb8704" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">.m4a</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> An audio-only MPEG-4 file, used by Apple for unprotected music downloaded from their iTunes Music Store. Audio within the m4a file is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">typically encoded with AAC, although lossless ALAC</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> may also be used.</mark></span></span></p></div><div id="https://www.notion.so/7db341d59a974dd18aea230491ee8a83" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">音频文件存储:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/9940c64f9e9d4c5fab9d2026028972dc" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">WAV(Waveform Audio File Format):</mark></span></span></li><li id="https://www.notion.so/182429b3e3f243b9ade84cfaad13fb61" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**普遍支持**:WAV是最广泛支持的音频文件格式之一,由微软开发,原生支持LPCM音频流。</mark></span></span></li><li id="https://www.notion.so/6b14fdbf66a6430ca11b2dbc7f5fa52a" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**无损质量**:WAV文件可以无损存储LPCM音频数据,保持原始音频质量。</mark></span></span></li><li id="https://www.notion.so/4b853e268fb647fcaff22a68240df466" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**元数据支持**:WAV格式支持存储关于音频流的详细信息,如采样率、位深度、声道数等。</mark></span></span></li><li id="https://www.notion.so/60f24c8b29694691aa26ab7b03c79302" class="NumberedList" value="5"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**文件大小**:由于WAV文件通常不使用压缩,文件大小可能会非常大,尤其是对于高采样率、高位深度、多声道音频。</mark></span></span></li><li id="https://www.notion.so/a88dbab85eaa4729a3b0560f3284eb99" class="NumberedList" value="6"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">AIFF(Audio Interchange File Format)</mark></span></span></li><li id="https://www.notion.so/d5835f410f9445b4857fd42bf4771c94" class="NumberedList" value="7"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**类似WAV**:AIFF是苹果公司开发的一种音频文件格式,与WAV非常相似,提供无损音频质量和广泛的元数据支持。</mark></span></span></li><li id="https://www.notion.so/bdb02087c2f648a68f33fadf818d376f" class="NumberedList" value="8"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**跨平台**:虽然AIFF最初是为Macintosh系统设计的,但现在它在多个平台上都得到支持。</mark></span></span></li><li id="https://www.notion.so/0e16d51ac258472091c184a444c6daff" class="NumberedList" value="9"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**文件大小**:和WAV一样,AIFF文件也可能相当大,特别是当存储高质量的多声道LPCM音频时。</mark></span></span></li><li id="https://www.notion.so/a2f33e706c044868a30cccff92e6a18e" class="NumberedList" value="10"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">FLAC(Free Lossless Audio Codec)</mark></span></span></li><li id="https://www.notion.so/008fbf04c38d4a45bc5d9124503d208f" class="NumberedList" value="11"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**无损压缩**:FLAC提供无损压缩,能够在不损失音质的情况下减小文件大小,适用于LPCM音频数据。</mark></span></span></li><li id="https://www.notion.so/d96a26472f4a42689b5d387e1f93dd19" class="NumberedList" value="12"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**标签和元数据**:FLAC支持丰富的标签和元数据,方便音乐管理和播放器识别。</mark></span></span></li><li id="https://www.notion.so/06ce5be892f645188773696d472eedb8" class="NumberedList" value="13"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**广泛支持**:尽管主要用于立体声音频,FLAC格式也支持多达8个声道的音频,适用于多声道LPCM音频流的存储。</mark></span></span></li><li id="https://www.notion.so/3d91a4f92b464834a98f5e922dd6b6e6" class="NumberedList" value="14"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Multichannel WAV/RF64</mark></span></span></li><li id="https://www.notion.so/c30f13985e6c46e9a1f6ad7e731d0420" class="NumberedList" value="15"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**大型文件**:为了克服WAV文件对文件大小的限制(4GB),扩展格式如RF64被设计用来支持更大的文件,适合长时间的高质量多声道录音。</mark></span></span></li><li id="https://www.notion.so/a40f3cec48714f43b3190c7623f042d9" class="NumberedList" value="16"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**广泛兼容性**:这些格式保持了与标准WAV格式的向后兼容性,同时扩展了其能力,以支持更大的数据量。</mark></span></span></li></ol><div id="https://www.notion.so/e0b80e5c96cf47878506f6b2b8606ff3" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">存储过程:存储多声道LPCM音频流通常涉及以下步骤:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/a0992af828b64766be64a48416dcd77b" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**选择格式**:根据需要支持的声道数、对音质的要求以及对文件大小的考虑,选择合适的音频文件格式。</mark></span></span></li><li id="https://www.notion.so/41abc276bd88471ba03b2949f6c1a928" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**准备音频数据**:将LPCM编码的音频数据按照选择的格式要求(如声道排列、采样率、位深度等)进行组织。</mark></span></span></li><li id="https://www.notion.so/1c0cc670f7474a5c966f78323ceaf452" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**写入文件**:将音频数据连同必要的元数据(如格式头信息)一起写入到文件中。</mark></span></span></li><li id="https://www.notion.so/eba9f12d32404625b77e0dd0dbb616fb" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">**验证**:确保写入的音频文件符合所选格式的规范,并且可以被目标播放器或编辑软件正确读取。</mark></span></span></li></ol><div id="https://www.notion.so/a337b01d696b4e0c802185bfeab4c44d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用适当的音频编辑或编码软件,你可以轻松地将多声道LPCM音频流保存到这些格式的文件中,无论是通过图形用户界面操作还是通过编程方式。</mark></span></span></p></div><h2 id="https://www.notion.so/c1db010d2f604a02aec50cbf85f7ddfd" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/c1db010d2f604a02aec50cbf85f7ddfd"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">2 I2S 接口和播放声音 </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-audio/#i2s-%E6%8E%A5%E5%8F%A3%E5%92%8C%E6%92%AD%E6%94%BE%E5%A3%B0%E9%9F%B3"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/e44da5f8ea204ebf9fc8970838c2f754" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">一般来说,一个语音提示文件的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MP3 </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">格式的大小约 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">5KB</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">,而未压缩的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">格式的大小则为 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">60KB </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">左右。如果拿 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">2MB </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">FLASH </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">空间来存储 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MP3 </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">格式的语音提示文件,则其数量要远大于 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">WAV </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">格式。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/2a18562145f64a93b12304a8b89fdf80" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">保存的是未压缩的 PCM 数据,可以直接通过 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">接口发送给数字音频芯片来播放。</mark></span></span></li></ul><div id="https://www.notion.so/2a16c06e4982472bb292ca63a315ccdc" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">而其他格式如 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MP3</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, 需要通过软件或硬件解码为 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 格式 ,然后才能通过 I2S 数字音频接口发送给功放芯片。</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/fec01113ddca482fb7f0ea80e44f2545" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2C</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">协议来配置WM8978模块</mark></span></span></li><li id="https://www.notion.so/a2f176a50ddd46cab2f4d8f6314c626b" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">初始化</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ESP32</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">的</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">通信接口</mark></span></span></li><li id="https://www.notion.so/db86c5d29f184d7fba86b18b8f98fd23" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">建立数据缓冲,大于</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">4096</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">字节</mark></span></span></li><li id="https://www.notion.so/aeaed4ece57e4f679b65c977cdfac5d6" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">从</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">FLASH</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">读取一个扇区(</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">4096</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">字节)</mark></span></span></li><li id="https://www.notion.so/4e4d16c1fc0147e1ae9586134ad0ceb5" class="NumberedList" value="5"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">转为解码所需的</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">stream</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">比特流形式(如开源的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">mad MP3</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 解码库 )</mark></span></span></li><li id="https://www.notion.so/e5bf48f0bc014a3190657359d000cb36" class="NumberedList" value="6"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">开始</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MP3</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">解码</mark></span></span></li><li id="https://www.notion.so/48c4eb120e4940b2a108e8dd35a7ce62" class="NumberedList" value="7"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">解码</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">4096</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">字节完成后,把 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">数据 通过</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">送入</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">WM8978</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">模块</mark></span></span></li></ol><div id="https://www.notion.so/544c7432c34d4a8a9930f28a43f1251c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">综上:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/7e916512f47b4fe7b70d1458af07d1c2" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用 ESP32 播放 mp3 文件前,都需要解码,解码输出的格式为 PCM:</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/ba26fa6d71494310a1d8bd4499f9db37" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">开源的 MAD (MPEG Audio Decoder) MP3 解码库 :</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://www.underbit.com/products/mad/"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://www.underbit.com/products/mad/</mark></a></span></span></li><li id="https://www.notion.so/d9bceafccb664fe585529969dce340c3" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">ESP32 Box S3 的 </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/chmorgan/esp-audio-player"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">esp-audio-player</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 使用的 libhelix-mp3 解码库:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/ultraembedded/libhelix-mp3/tree/master"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/ultraembedded/libhelix-mp3/tree/master</mark></a></span></span></li><li id="https://www.notion.so/5bca2b7e41de4d98a4b716e5c5a5f704" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">开源的 ESP32-audioI2S:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/schreibfaul1/ESP32-audioI2S"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/schreibfaul1/ESP32-audioI2S</mark></a></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/fa736d8755364b37ab89ac00389f3c34" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">可以解码播放: </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">mp3, m4a</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> and wav files from SD card via I2S,HELIX-mp3 and -aac decoder is included. There is also an OPUS decoder for Fullband, n VORBIS decoder( </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">.ogg 格式</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">) and </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">a FLAC decoder</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">.</mark></span></span></li></ul></li></ul></li><li id="https://www.notion.so/c3e3fde230e2409fae0faba989b3581e" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">然后将解码后的 PCM 编码数据通过 I2S 接口发送给数字音频功放芯片(codec chip);</mark></span></span></li><li id="https://www.notion.so/589bb7dcaa694b1eb570c31c34660f0b" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">功放芯片进行 DAC 转换,驱动扬声器;</mark></span></span></li><li id="https://www.notion.so/1eec70b0c53441b8bb333c265bb23f9b" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">对于支持 MIC 输入的 codec chip,drvier 也通过 I2S 接口来读取 ADC 后的音频 PCM 数据,然后进一步处理,如 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">直接保存为未编码的 wav 格式文件</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,或经过压缩后编码为其他格式,如 mp3、aac 等来存储到 TF 卡,或者再发送给 codec chip 来播放;</mark></span></span></li></ol><div id="https://www.notion.so/4a1ffd8b3ee2462cb1c0e8f7609ff5b6" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">注:I2S 接口是数字音频信号的传输协议(不一定是物理接口),而 PCM 是数字音频的编码格式,可以经过 DAC 直接转换为模拟信号。</mark></span></span></p></div><div id="https://www.notion.so/cfd6e57ea5d5493daf394ca67ed968f2" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">大一统的 ESP32-audioI2S 解码播放示例:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/schreibfaul1/ESP32-audioI2S"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/schreibfaul1/ESP32-audioI2S</mark></a></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/2ec8d52cd3d84d26bac45f89f6670191" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">实际项目: </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/Makerfabs/Project_MakePython_Audio_Music"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/Makerfabs/Project_MakePython_Audio_Music</mark></a></span></span></li></ul><div id="https://www.notion.so/7b5059ff80034362a0de0a2468305ab9" class="Image Image--PageWidth"><figure><a href="#?width=654"><img src="#?width=654" style="width:100%"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/c10e7f3cdba5472bbb908571d4a8a31d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/3f4bdcf57b0a412a8389b7b1bd95ac6f" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span>// https://github.com/schreibfaul1/ESP32-audioI2S
#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"
#include "SD.h"
#include "FS.h"
// Digital I/O used
#define SD_CS 5
#define SPI_MOSI 23
#define SPI_MISO 19
#define SPI_SCK 18
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26
Audio audio;
String ssid = "*******";
String password = "*******";
void setup() {
pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
Serial.begin(115200);
SD.begin(SD_CS);
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED) delay(1500);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(21); // default 0...21
// or alternative
// audio.setVolumeSteps(64); // max 255
// audio.setVolume(63);
//
// *** radio streams ***
audio.connecttohost("http://stream.antennethueringen.de/live/aac-64/stream.antennethueringen.de/"); // aac
// audio.connecttohost("http://mcrscast.mcr.iol.pt/cidadefm"); // mp3
// audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u"); // m3u
// audio.connecttohost("https://stream.srg-ssr.ch/rsp/aacp_48.asx"); // asx
// audio.connecttohost("http://tuner.classical102.com/listen.pls"); // pls
// audio.connecttohost("http://stream.radioparadise.com/flac"); // flac
// audio.connecttohost("http://stream.sing-sing-bis.org:8000/singsingFlac"); // flac (ogg)
// audio.connecttohost("http://s1.knixx.fm:5347/dein_webradio_vbr.opus"); // opus (ogg)
// audio.connecttohost("http://stream2.dancewave.online:8080/dance.ogg"); // vorbis (ogg)
// audio.connecttohost("http://26373.live.</span></span><span class="SemanticString"><span>streamtheworld.com:3690/XHQQ_FMAAC/HLSTS/playlist.m3u8"); // HLS
// audio.connecttohost("http://eldoradolive02.akamaized.net/hls/live/2043453/eldorado/master.m3u8"); // HLS (ts)
// *** web files ***
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/Pink-Panther.wav"); // wav
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/Santiano-Wellerman.flac"); // flac
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/Olsen-Banden.mp3"); // mp3
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/Miss-Marple.m4a"); // m4a (aac)
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/Collide.ogg"); // vorbis
// audio.connecttohost("https://github.com/schreibfaul1/ESP32-audioI2S/raw/master/additional_info/Testfiles/sample.opus"); // opus
// *** local files ***
// audio.connecttoFS(SD, "/test.wav"); // SD
// audio.connecttoFS(SD_MMC, "/test.wav"); // SD_MMC
// audio.connecttoFS(SPIFFS, "/test.wav"); // SPIFFS
// audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); // Google TTS
}
void loop()
{
audio.loop();
}
// optional
void audio_info(const char *info){
Serial.print("info "); Serial.println(info);
}
void audio_id3data(const char *info){ //id3 metadata
Serial.print("id3data ");Serial.println(info);
}
void audio_eof_mp3(const char *info){ //end of file
Serial.print("eof_mp3 ");Serial.println(info);
}
void audio_showstation(const char *info){
Serial.print("station ");Serial.println(info);
}
void audio_showstreamtitle(const char *info){
Serial.print("streamtitle ");Serial.println(info);
}
void audio_bitrate(const char *info){
Serial.print("bitrate </span></span><span class="SemanticString"><span> ");Serial.println(info);
}
void audio_commercial(const char *info){ //duration in sec
Serial.print("commercial ");Serial.println(info);
}
void audio_icyurl(const char *info){ //homepage
Serial.print("icyurl ");Serial.println(info);
}
void audio_lasthost(const char *info){ //stream URL played
Serial.print("lasthost ");Serial.println(info);
}
void audio_eof_speech(const char *info){
Serial.print("eof_speech ");Serial.println(info);
}</span></span></span></code></pre><div id="https://www.notion.so/a9f1e9f63dae46e19ecc4fd1216b58f9" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">对于数字音频功放芯片,一般也称为 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">codec chip</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/333158aa646f4237ae1e37f7ec5bf994" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">将 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">数字音频解码,然后 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">DAC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">转换为模型信号输出;</mark></span></span></li><li id="https://www.notion.so/0a2f910700e84d96a42952233bc1dfd3" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">将 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">收到的模拟声音信号经过 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ADC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">转换,然后编码为 PCM 数字比特流;</mark></span></span></li><li id="https://www.notion.so/cf9f412e6fe74e23bdbbfb07a291a233" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">driver 都是通过 I2S 接口来发送和接受 PCM 数字信号;</mark></span></span></li></ol><div id="https://www.notion.so/a096a4f2dc0f40f3993e4f3cd85fc329" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Wm8960 is a low power, high quality stereo CODEC, that provides two interface types: voice input and output. The communication between ESP32 and WM8960 is I2S.</mark></span></span></p></div><div id="https://www.notion.so/8876834162ad43b4ab675017b5c4b84f" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">一般 I2S 接口的数字音频功放芯片 codec chip,除了可以播放 PCM 编码格式的数字音频信号外,还提供控制(静音、音量大小等)和 MIC 输入功能,如 </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://docs.espressif.com/projects/esp-adf/en/latest/api-reference/abstraction/es8374.html"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">ES8374</mark></a></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/69729fe74d024e069f9b3cc9b52c19a7" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">codec chip 的 MIC 将 ADC 转换为 PCM 编码数据,driver 可以通过 I2S 接口来读取这些数据,进行后续处理,如编码后保存到 TF 卡或者播放。</mark></span></span></li></ul><div id="https://www.notion.so/4b7bcd3253974f01ae9c250383907e93" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">示例:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/espressif/esp-box/blob/master/examples/usb_headset/main/src/usb_headset.c"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/espressif/esp-box/blob/master/examples/usb_headset/main/src/usb_headset.c</mark></a></span></span></p></div><div id="https://www.notion.so/1519c204c31f41a288aa9911ec516336" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">如果需要更好的音频质量和更多的接口选项,可使用外部 I2S 编解码器来完成所有模拟输入和输出信号的处理。不同类型的编解码器芯片可提供不同的额外功能,如音频输入信号前置放大器、耳机输出放大器、多个模拟输入和输出、音效处理等。I2S 是音频编解码器芯片接口的行业标准,通常用于高速、连续传输音频数据。为了优化音频数据处理的性能,可能需要额外的内存。对于这种情况,请考虑使用集成 8 MB PSRAM 和 ESP32 芯片的 ESP32-WROVER-E 模组。</mark></span></span></p></div><div id="https://www.notion.so/b0a14a2a59f840f3bc7e5b27fd29f411" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/project-design.html"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/project-design.html</mark></a></span></span></p></div><div id="https://www.notion.so/c7b81c317eb54e6187d956f510bc3fbe" class="Image Image--Normal"><figure><a href="#?width=480"><img src="#?width=480" style="width:480px"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/81cd14134dbc45e38d719c89ac763886" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">ESP32 提供了乐鑫音频开发框架(ADF),支持常见的编解码格式: </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://docs.espressif.com/projects/esp-adf/en/latest/index.html"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://docs.espressif.com/projects/esp-adf/en/latest/index.html</mark></a></span></span></p></div><div id="https://www.notion.so/2990ca89fbf3458da5fc58af048571d1" class="Image Image--PageWidth"><figure><a href="#?width=540"><img src="#?width=540" style="width:100%"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/f8256f848b264b168b94541d94233594" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/63a3b8db673f4cf9831acac34c9e4a3d" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span>I (397) PLAY_FLASH_MP3_CONTROL: [ 1 ] Start audio codec chip
I (427) PLAY_FLASH_MP3_CONTROL: [ 2 ] Create audio pipeline, add all elements to pipeline, and subscribe pipeline event
I (427) PLAY_FLASH_MP3_CONTROL: [2.1] Create mp3 decoder to decode mp3 file and set custom read callback
I (437) PLAY_FLASH_MP3_CONTROL: [2.2] Create i2s stream to write data to codec chip
I (467) PLAY_FLASH_MP3_CONTROL: [2.3] Register all elements to audio pipeline
I (467) PLAY_FLASH_MP3_CONTROL: [2.4] Link it together [mp3_music_read_cb]-->mp3_decoder-->i2s_stream-->[codec_chip]
I (477) PLAY_FLASH_MP3_CONTROL: [ 3 ] Set up event listener
I (477) PLAY_FLASH_MP3_CONTROL: [3.1] Listening event from all elements of pipeline
I (487) PLAY_FLASH_MP3_CONTROL: [ 4 ] Start audio_pipeline
I (507) PLAY_FLASH_MP3_CONTROL: [ * ] Receive music info from mp3 decoder, sample_rates=44100, bits=16, ch=2
I (7277) PLAY_FLASH_MP3_CONTROL: [ 5 ] Stop audio_pipeline</span></span></span></code></pre><div id="https://www.notion.so/0f3db7cbba11408080ade05446342d72" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">示例:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/espressif/esp-adf/tree/master/examples"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/espressif/esp-adf/tree/master/examples</mark></a></span></span></p></div><h2 id="https://www.notion.so/7fa6c972d3e84186a4d9b5e2d3af47a3" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/7fa6c972d3e84186a4d9b5e2d3af47a3"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">3 记录声音 </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-audio/#%E8%AE%B0%E5%BD%95%E5%A3%B0%E9%9F%B3"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/e939fd693e33442cadeecb2fe5f9fcbf" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用麦克风 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Module </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">如 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">INMP441 module</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 来将声音转换为数字信号(</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">编码后的数字流),然后 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ESP32 driver</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 通过 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">接口来获取数字音频。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/bc330c4053234e28be2bd30b6c7dbb5c" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">INMP441 module will be acting as a mic input for capturing mono 16-bit audio signals at rate 8000 samples per second.</code></mark></span></span></li><li id="https://www.notion.so/11a42d55b7184fbf8aea9d91a457052c" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">一般数字音频功放芯片集成有 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">,也是通过 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">接口来获取 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 数据,所以也称为 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">codec chip</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">。</mark></span></span></li></ul><div id="https://www.notion.so/670449e0946041ca8dd5b58372bc54e5" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">如果是模拟 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">则可以使用 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ESP32 </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">的 ADC 引脚转换为 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">,然后再保存到 wav 文件中。</mark></span></span></p></div><div id="https://www.notion.so/6c4a7e63fbd648f5a1fb060544b7d4f7" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">通过 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">从 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">读取 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PCM </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">数字音频后,以 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">文件格式存入 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">SD </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">卡:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/23029baa7f2e47a79c4a7c8d36171c6a" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">文件:</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">medatadata header + LPCM raw data</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">;</mark></span></span></li></ul><div id="https://www.notion.so/1a3a8714bc8d4efb85fe856f780f63d6" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/9f762ceee3f5445f8a3251f58825faa4" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment">// https://www.makerfabs.com/blog/post/how-to-make-an-esp32-sound-recorder</span>
<span class="token keyword">void</span> <span class="token function">WM8960_Record</span><span class="token punctuation">(</span>String filename<span class="token punctuation">,</span> <span class="token keyword">char</span> <span class="token operator">*</span>buff<span class="token punctuation">,</span> <span class="token keyword">int</span> record_time<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">int</span> headerSize <span class="token operator">=</span> <span class="token number">44</span><span class="token punctuation">;</span>
byte header<span class="token punctuation">[</span>headerSize<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> waveDataSize <span class="token operator">=</span> record_time <span class="token operator">*</span> <span class="token number">16000</span> <span class="token operator">*</span> <span class="token number">16</span> <span class="token operator">*</span> <span class="token number">2</span> <span class="token operator">/</span> <span class="token number">8</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> recode_time <span class="token operator">=</span> <span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> part_time <span class="token operator">=</span> recode_time<span class="token punctuation">;</span>
File file <span class="token operator">=</span> SD<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> FILE_WRITE<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>file<span class="token punctuation">)</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Begin to record:"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator"><</span> waveDataSize <span class="token operator">/</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>buff<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">++</span>j<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">I2S_Read</span><span class="token punctuation">(</span>buff<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>buff<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
file<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">const</span> byte <span class="token operator">*</span><span class="token punctuation">)</span>buff<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>buff<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> part_time<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">1000</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Serial<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
part_time <span class="token operator">=</span> <span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
file<span class="token punctuation">.</span><span class="token function">seek</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">CreateWavHeader</span><span class="token punctuation">(</span>header<span class="token punctuation">,</span> waveDataSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
file<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>header<span class="token punctuation">,</span> headerSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Finish"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> recode_time<span class="token punctuation">)</span><span class="token punctuation">;</span>
file<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></span></span></span></code></pre><div id="https://www.notion.so/d60b47e315cb44d8bc7eca8b2f0c4b41" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">播放 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">文件:</mark></span></span></p></div><div id="https://www.notion.so/472827dab7b940e2887c6d93cf13e755" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/19b1b765f3cb43119f3b56bc3b29bfba" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment">// https://www.makerfabs.com/blog/post/how-to-make-an-esp32-sound-recorder</span>
<span class="token keyword">void</span> <span class="token function">WM8960_Play</span> <span class="token punctuation">(</span>String filename<span class="token punctuation">,</span> <span class="token keyword">char</span> <span class="token operator">*</span>buff<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
File file <span class="token operator">=</span> SD<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>filename<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span> file<span class="token punctuation">)</span>
<span class="token keyword">return</span>;
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Begin to play:"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>filename<span class="token punctuation">)</span><span class="token punctuation">;</span>
file<span class="token punctuation">.</span><span class="token function">seek</span><span class="token punctuation">(</span><span class="token number">44</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 跳过 wav header</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>file<span class="token punctuation">.</span><span class="token function">readBytes</span><span class="token punctuation">(</span>buff<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>buff<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">I2S_Write</span><span class="token punctuation">(</span>buff<span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>buff<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Finish"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
file<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></span></span></span></code></pre><div id="https://www.notion.so/429325862ccd4d6c8ae4ab57a4dda8d1" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">另一个使用 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">从 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">读取数据,存入 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">文件的例子: </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/MhageGH/esp32_SoundRecorder/tree/master">https://github.com/MhageGH/esp32_SoundRecorder/tree/master</a></mark></span></span></p></div><div id="https://www.notion.so/91dfe77640f546bc88fd4f05d62aee3b" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/e933b2aed99140ccaf3af56e45e99884" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"Arduino.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><FS.h></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"Wav.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"I2S.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><SD.h></span></span>
<span class="token comment">//comment the first line and uncomment the second if you use MAX9814</span>
<span class="token comment">//#define I2S_MODE I2S_MODE_RX</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">I2S_MODE</span> <span class="token expression">I2S_MODE_ADC_BUILT_IN</span></span>
<span class="token keyword">const</span> <span class="token keyword">int</span> record_time <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span> <span class="token comment">// second</span>
<span class="token keyword">const</span> <span class="token keyword">char</span> filename<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"/sound.wav"</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> headerSize <span class="token operator">=</span> <span class="token number">44</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> waveDataSize <span class="token operator">=</span> record_time <span class="token operator">*</span> <span class="token number">88000</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> numCommunicationData <span class="token operator">=</span> <span class="token number">8000</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> numPartWavData <span class="token operator">=</span> numCommunicationData<span class="token operator">/</span><span class="token number">4</span><span class="token punctuation">;</span>
byte header<span class="token punctuation">[</span>headerSize<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">char</span> communicationData<span class="token punctuation">[</span>numCommunicationData<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">char</span> partWavData<span class="token punctuation">[</span>numPartWavData<span class="token punctuation">]</span><span class="token punctuation">;</span>
File file<span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
Serial<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token number">115200</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>SD<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"SD begin failed"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token operator">!</span>SD<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
Serial<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">delay</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">CreateWavHeader</span><span class="token punctuation">(</span>header<span class="token punctuation">,</span> waveDataSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
SD<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span>filename<span class="token punctuation">)</span><span class="token punctuation">;</span>
file <span class="token operator">=</span> SD<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> FILE_WRITE<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>file<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>
file<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>header<span class="token punctuation">,</span> headerSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">I2S_Init</span><span class="token punctuation">(</span>I2S_MODE<span class="token punctuation">,</span> I2S_BITS_PER_SAMPLE_32BIT<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator"><</span> waveDataSize<span class="token operator">/</span>numPartWavData<span class="token punctuation">;</span> <span class="token operator">++</span>j<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">I2S_Read</span><span class="token punctuation">(</span>communicationData<span class="token punctuation">,</span> numCommunicationData<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> numCommunicationData<span class="token operator">/</span><span class="token number">8</span><span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
partWavData<span class="token punctuation">[</span><span class="token number">2</span><span class="token operator">*</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> communicationData<span class="token punctuation">[</span><span class="token number">8</span><span class="token operator">*</span>i <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
partWavData<span class="token punctuation">[</span><span class="token number">2</span><span class="token operator">*</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> communicationData<span class="token punctuation">[</span><span class="token number">8</span><span class="token operator">*</span>i <span class="token operator">+</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
file<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">const</span> byte<span class="token operator">*</span><span class="token punctuation">)</span>partWavData<span class="token punctuation">,</span> numPartWavData<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
file<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"finish"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">loop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token comment">// wav 头文件</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"Wav.h"</span></span>
<span class="token keyword">void</span> <span class="token function">CreateWavHeader</span><span class="token punctuation">(</span>byte<span class="token operator">*</span> header<span class="token punctuation">,</span> <span class="token keyword">int</span> waveDataSize<span class="token punctuation">)</span><span class="token punctuation">{</span>
header<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'R'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'I'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'F'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'F'</span><span class="token punctuation">;</span>
<span class="token keyword">unsigned</span> <span class="token keyword">int</span> fileSizeMinus8 <span class="token operator">=</span> waveDataSize <span class="token operator">+</span> <span class="token number">44</span> <span class="token operator">-</span> <span class="token number">8</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span>fileSizeMinus8 <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fileSizeMinus8 <span class="token operator">>></span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fileSizeMinus8 <span class="token operator">>></span> <span class="token number">16</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">7</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fileSizeMinus8 <span class="token operator">>></span> <span class="token number">24</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'W'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">9</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'A'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'V'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">11</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'E'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">12</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'f'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">13</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'m'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">14</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'t'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">15</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">' '</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">16</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x10</span><span class="token punctuation">;</span> <span class="token comment">// linear PCM</span>
header<span class="token punctuation">[</span><span class="token number">17</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">18</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">19</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">20</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x01</span><span class="token punctuation">;</span> <span class="token comment">// linear PCM</span>
header<span class="token punctuation">[</span><span class="token number">21</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">22</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x01</span><span class="token punctuation">;</span> <span class="token comment">// monoral</span>
header<span class="token punctuation">[</span><span class="token number">23</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">24</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x44</span><span class="token punctuation">;</span> <span class="token comment">// sampling rate 44100</span>
header<span class="token punctuation">[</span><span class="token number">25</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0xAC</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">26</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">27</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">28</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x88</span><span class="token punctuation">;</span> <span class="token comment">// Byte/sec = 44100x2x1 = 88200</span>
header<span class="token punctuation">[</span><span class="token number">29</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x58</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">30</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x01</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">31</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x02</span><span class="token punctuation">;</span> <span class="token comment">// 16bit monoral</span>
header<span class="token punctuation">[</span><span class="token number">33</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">34</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x10</span><span class="token punctuation">;</span> <span class="token comment">// 16bit</span>
header<span class="token punctuation">[</span><span class="token number">35</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">36</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'d'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">37</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'a'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">38</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'t'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">39</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token char">'a'</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">40</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span>waveDataSize <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">41</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>waveDataSize <span class="token operator">>></span> <span class="token number">8</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">42</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>waveDataSize <span class="token operator">>></span> <span class="token number">16</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
header<span class="token punctuation">[</span><span class="token number">43</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>byte<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">(</span>waveDataSize <span class="token operator">>></span> <span class="token number">24</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></span></span></span></code></pre><div id="https://www.notion.so/4836dfcaf6a6400f81326832aa63f57f" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">除了 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I2S </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">接口的数字 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">外,常见的还有 模拟输出的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">MIC</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,这时可以使用 ESP32 的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ADC</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 引脚来进行模数转换 ,将结果以 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">LPCM </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">编码的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">wav </code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">文件保存:</mark></span></span></p></div><div id="https://www.notion.so/399343a649484dbcb95942f4ce8ec611" class="Image Image--Normal"><figure><a href="#?width=336"><img src="#?width=336" style="width:336px"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/c365fb9f1ba441cf9c6e4e1c302f058a" class="Image Image--Normal"><figure><a href="#?width=528"><img src="#?width=528" style="width:528px"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/e9137780db5c4afa975d754b695cb251" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/1c7a8cd1c1fc4fbebe52640ca3d06ae1" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment">// https://github.com/AlirezaSalehy/WAVRecorder/blob/main/library/library.ino</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><SD.h></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><SPI.h></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"src/WAVRecorder.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"src/AudioSystem.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"src/SoundActivityDetector.h"</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">SAMPLE_RATE</span> <span class="token expression"><span class="token number">16000</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">SAMPLE_LEN</span> <span class="token expression"><span class="token number">8</span></span></span>
<span class="token comment">// Hardware SPI's CS pin which is different in each board</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ifdef</span> <span class="token expression">ESP8266</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">CS_PIN</span> <span class="token expression"><span class="token number">16</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">elif</span> <span class="token expression">ARDUINO_SAM_DUE</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">CS_PIN</span> <span class="token expression"><span class="token number">4</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">elif</span> <span class="token expression">ESP32</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">CS_PIN</span> <span class="token expression"><span class="token number">5</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token comment">// The analog pins (ADC inputs) which microphone outputs are connected to.</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">MIC_PIN_1</span> <span class="token expression"><span class="token number">34</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">MIC_PIN_2</span> <span class="token expression"><span class="token number">35</span></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">NUM_CHANNELS</span> <span class="token expression"><span class="token number">1</span></span></span>
channel_t channels<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">{</span>MIC_PIN_1<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">char</span> file_name<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"/sample.wav"</span><span class="token punctuation">;</span>
File dataFile<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token function">defined</span><span class="token punctuation">(</span>ESP32<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token function">defined</span><span class="token punctuation">(</span>ESP8266<span class="token punctuation">)</span></span></span>
AudioSystem<span class="token operator">*</span> as<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
WAVRecorder<span class="token operator">*</span> wr<span class="token punctuation">;</span>
<span class="token comment">//SoundActivityDetector* sadet;</span>
<span class="token keyword">void</span> <span class="token function">recordAndPlayBack</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>channels<span class="token punctuation">)</span><span class="token operator">/</span><span class="token keyword">sizeof</span><span class="token punctuation">(</span>channel_t<span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
<span class="token function">pinMode</span><span class="token punctuation">(</span>channels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>ADCPin<span class="token punctuation">,</span> INPUT<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//analogReadResolution(12); for ESP32</span>
<span class="token function">pinMode</span><span class="token punctuation">(</span>LED_BUILTIN<span class="token punctuation">,</span> OUTPUT<span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token number">115200</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// put your setup code here, to run once:</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>SD<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span>CS_PIN<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Failes to initialize SD!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token punctuation">{</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"SD opened successfuly"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
SPI<span class="token punctuation">.</span><span class="token function">setClockDivider</span><span class="token punctuation">(</span>SPI_CLOCK_DIV2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// This is becuase feeding SD Card with more than 40 Mhz, leads to unstable operation.</span>
<span class="token comment">// (Also depends on SD class) ESP8266 & ESP32 SPI clock with no division is 80 Mhz.</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token function">defined</span><span class="token punctuation">(</span>ESP32<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token function">defined</span><span class="token punctuation">(</span>ESP8266<span class="token punctuation">)</span></span></span>
as <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">AudioSystem</span><span class="token punctuation">(</span>CS_PIN<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token comment">//sadet = new SoundActivityDetector(channels[0].ADCPin, 2000, 10 * 512, 6 * 512, &Serial);</span>
wr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">WAVRecorder</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">,</span> channels<span class="token punctuation">,</span> NUM_CHANNELS<span class="token punctuation">,</span> SAMPLE_RATE<span class="token punctuation">,</span> SAMPLE_LEN<span class="token punctuation">,</span> <span class="token operator">&</span>Serial<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">loop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// put your main code here, to run repeatedly:</span>
<span class="token function">recordAndPlayBack</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">recordAndPlayBack</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>SD<span class="token punctuation">.</span><span class="token function">exists</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
SD<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"File removed!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
dataFile <span class="token operator">=</span> SD<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>file_name<span class="token punctuation">,</span> FILE_WRITE<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>dataFile<span class="token punctuation">)</span> <span class="token punctuation">{</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Failed to open the file!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Setting file to store recodring</span>
wr<span class="token operator">-></span><span class="token function">setFile</span><span class="token punctuation">(</span><span class="token operator">&</span>dataFile<span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Started"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// With checks Sound power level and it exceeds a threshold recording starts and stops recording when power fall behind another threshold.</span>
<span class="token comment">//wr->startBlocking(sadet);</span>
<span class="token comment">// Recording for 3000 ms</span>
wr<span class="token operator">-></span><span class="token function">startBlocking</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"File Created"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Serial<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Playing file"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token function">defined</span><span class="token punctuation">(</span>ESP32<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token function">defined</span><span class="token punctuation">(</span>ESP8266<span class="token punctuation">)</span></span></span>
as<span class="token operator">-></span><span class="token function">playAudioBlocking</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token punctuation">}</span></span></span></span></code></pre><div id="https://www.notion.so/672887daf631417385448768115cde09" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><div id="https://www.notion.so/23be38f5848345a7a1d2b69864db6d87" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">另一个例子:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://www.youtube.com/watch?v=qq2FRv0lCPw"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Broadcasting Your Voice with ESP32-S3 & INMP441</mark></a></span></span></p></div><div id="https://www.notion.so/35a575930bb34346a710a8e8505d43b7" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><div id="https://www.notion.so/c244c959424a42a2bedbbefe17552711" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">The ESP32-S3’s I2S interface is set up to handle the audio data using Direct Memory Access (DMA) buffers. DMA allows for efficient data transfer without involving the main processor, offloading the task to a dedicated DMA controller. By configuring the DMA buffer in I2S, the captured audio samples can be stored and transmitted seamlessly.</mark></span></span></p></div><div id="https://www.notion.so/2369c00d46d44d0c8ac76cc2ae7b9848" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/0015/ThatProject/blob/master/ESP32_MICROPHONE/Broadcasting_Your_Voice/ESP32-S3_INMP441_WebSocket_Client/ESP32-S3_INMP441_WebSocket_Client.ino">ESP32-S3_INMP441_WebSocket_Client.ino</a></span></span></p></div><div id="https://www.notion.so/af372967ce2b4d0492d06b652a99f58e" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/03c3af0e0188439cb3ea80d3ad0fb146" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token keyword">void</span> <span class="token function">i2s_install</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Set up I2S Processor configuration</span>
<span class="token keyword">const</span> i2s_config_t i2s_config <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span>mode <span class="token operator">=</span> <span class="token function">i2s_mode_t</span><span class="token punctuation">(</span>I2S_MODE_MASTER <span class="token operator">|</span> I2S_MODE_RX<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>sample_rate <span class="token operator">=</span> <span class="token number">44100</span><span class="token punctuation">,</span>
<span class="token comment">//.sample_rate = 16000,</span>
<span class="token punctuation">.</span>bits_per_sample <span class="token operator">=</span> <span class="token function">i2s_bits_per_sample_t</span><span class="token punctuation">(</span><span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>channel_format <span class="token operator">=</span> I2S_CHANNEL_FMT_ONLY_LEFT<span class="token punctuation">,</span>
<span class="token punctuation">.</span>communication_format <span class="token operator">=</span> <span class="token function">i2s_comm_format_t</span><span class="token punctuation">(</span>I2S_COMM_FORMAT_STAND_I2S<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>intr_alloc_flags <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>dma_buf_count <span class="token operator">=</span> bufferCnt<span class="token punctuation">,</span>
<span class="token punctuation">.</span>dma_buf_len <span class="token operator">=</span> bufferLen<span class="token punctuation">,</span>
<span class="token punctuation">.</span>use_apll <span class="token operator">=</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">i2s_driver_install</span><span class="token punctuation">(</span>I2S_PORT<span class="token punctuation">,</span> <span class="token operator">&</span>i2s_config<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">micTask</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span> parameter<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">i2s_install</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">i2s_setpin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">i2s_start</span><span class="token punctuation">(</span>I2S_PORT<span class="token punctuation">)</span><span class="token punctuation">;</span>
size_t bytesIn <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
esp_err_t result <span class="token operator">=</span> <span class="token function">i2s_read</span><span class="token punctuation">(</span>I2S_PORT<span class="token punctuation">,</span> <span class="token operator">&</span>sBuffer<span class="token punctuation">,</span> bufferLen<span class="token punctuation">,</span> <span class="token operator">&</span>bytesIn<span class="token punctuation">,</span> portMAX_DELAY<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> ESP_OK <span class="token operator">&&</span> isWebSocketConnected<span class="token punctuation">)</span> <span class="token punctuation">{</span>
client<span class="token punctuation">.</span><span class="token function">sendBinary</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">char</span><span class="token operator">*</span><span class="token punctuation">)</span>sBuffer<span class="token punctuation">,</span> bytesIn<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></span></span></span></code></pre><div id="https://www.notion.so/e495630646214496b6b448e359857840" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">参考:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://diyi0t.com/i2s-sound-tutorial-for-esp32/"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://diyi0t.com/i2s-sound-tutorial-for-esp32/</mark></a></span></span></p></div><div id="https://www.notion.so/dce1e4417e7a4aefa8c84f0a0d493160" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><ul id="https://www.notion.so/62a87d1ea4b74cdaad2d92f686a1019a" class="ColorfulBlock ColorfulBlock--ColorGray TableOfContents"><li class="TableOfContents__Item"><a href="#https://www.notion.so/609d73b80c684fbeb23fd76032cfb034"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">1 音频格式 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li><li class="TableOfContents__Item"><a href="#https://www.notion.so/9f6d1f9c15374a6d80615e2983f80670"><div style="margin-left:24px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">总结</mark></span></span></div></a></li><li class="TableOfContents__Item"><a href="#https://www.notion.so/c1db010d2f604a02aec50cbf85f7ddfd"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">2 I2S 接口和播放声音 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li><li class="TableOfContents__Item"><a href="#https://www.notion.so/7fa6c972d3e84186a4d9b5e2d3af47a3"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">3 记录声音 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li></ul><div id="https://www.notion.so/85c9cd5a09cd4f128ed0719dc894456c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div></article>
<aside class="Aside">
<a href="#content-html"><div id="up">👆</div></a>
<a href="#message-board"><div id="down">👇</div></a>
</aside>
<div id="message-board"></div>
<script src="https://utteranc.es/client.js"
repo="syx-413/syx-413.github.io"
issue-term="pathname"
theme="boxy-light"
crossorigin="anonymous"
async>
</script>
<footer class="Footer">
<div>
© 413’s Website 2020~2024
</div>
<div>
·
</div>
<div>
Powered by
<a href="https://github.com/syx-413" target="_blank" rel="noopener noreferrer"> notablog</a>.
</div>
</footer>
</body>
</html>