- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试用 arduino 构建一个录音机。现在,该设置有一个麦克风记录输入和输出到 Arduino uno 的模拟输入。
如何将(时间戳、数据)读数转换为 .WAV?我知道有更多的库能够做到这一点,但我想了解 .WAV 的结构,并希望能够用 C\C++ 编写我自己的脚本。
感谢关注!
最佳答案
/// The first 4 byte of a wav file should be the characters "RIFF" */
char chunkID[4] = {'R', 'I', 'F', 'F'};
/// 36 + SubChunk2Size
uint32_t chunkSize = 36; // You Don't know this until you write your data but at a minimum it is 36 for an empty file
/// "should be characters "WAVE"
char format[4] = {'W', 'A', 'V', 'E'};
/// " This should be the letters "fmt ", note the space character
char subChunk1ID[4] = {'f', 'm', 't', ' '};
///: For PCM == 16, since audioFormat == uint16_t
uint32_t subChunk1Size = 16;
///: For PCM this is 1, other values indicate compression
uint16_t audioFormat = 1;
///: Mono = 1, Stereo = 2, etc.
uint16_t numChannels = 1;
///: Sample Rate of file
uint32_t sampleRate = 44100;
///: SampleRate * NumChannels * BitsPerSample/8
uint32_t byteRate = 44100 * 2;
///: The number of byte for one frame NumChannels * BitsPerSample/8
uint16_t blockAlign = 2;
///: 8 bits = 8, 16 bits = 16
uint16_t bitsPerSample = 16;
///: Contains the letters "data"
char subChunk2ID[4] = {'d', 'a', 't', 'a'};
///: == NumSamples * NumChannels * BitsPerSample/8 i.e. number of byte in the data.
uint32_t subChunk2Size = 0; // You Don't know this until you write your data
这里有一些假设,例如音频质量。以上假定 CD 质量音频 16 位,44.1kHz。如果您需要其他内容,则需要修改相关值。
您还需要注意您的 Arduino 是否真的定期记录样本,或者这是否本质上是数据的超声处理。
#include <SPI.h>
#include <SD.h>
File wavFile;
const char* filename = "data.wav";
void setup()
{
Serial.begin(9600);
while (!Serial);
if (!SD.begin(4))
while (1);
wavFile = SD.open(filename, FILE_WRITE);
if (!wavFile)
while (1);
}
鉴于 SD Library 的方式是有组织的,如果它们还不是 char
,则必须将 header 的元素转换为 byte
。 必须 可能有点强,但它确实可以更轻松地为 header 的每个元素维护正确的字节宽度,而不会弄得太多。
将 this 包装在它自己的函数中是有意义的。
void writeWavHeader()
{
wavFile.write(chunkID,4);
wavFile.write((byte*)&chunkSize,4);
wavFile.write(format,4);
wavFile.write(subChunk1ID,4);
wavFile.write((byte*)&subChunk1Size,4);
wavFile.write((byte*)&audioFormat,2);
wavFile.write((byte*)&numChannels,2);
wavFile.write((byte*)&sampleRate,4);
wavFile.write((byte*)&byteRate,4);
wavFile.write((byte*)&blockAlign,2);
wavFile.write((byte*)&bitsPerSample,2);
wavFile.write(subChunk2ID,4);
wavFile.write((byte*)&subChunk2Size,4);
}
wav header 告诉我们 chunkSize 和 subChunk2Size 取决于文件中的数据量。因此,如果您将数据附加到文件,这些将增长并且必须更改。
您可以通过多种方式获取有关添加数据的信息
您选择什么方法将取决于您的实现,我们没有太多信息。为了争论,让我们一次写一个示例。这种方法应该证明需要什么,缺点(经常在文件中跳转,大量重复)应该立即显而易见。
void writeDataToWavFile(int data)
{
int16_t sampleValue = map(data, MIN_DATA_VALUE, MAX_DATA_VALUE,-32767,32767);
subChunk2Size += numChannels * bitsPerSample/8;
wavFile.seek(40);
wavFile.write((byte*)&subChunk2Size,4);
wavFile.seek(4);
chunkSize = 36 + subChunk2Size;
wavFile.write((byte*)&chunkSize,4);
wavFile.seek(wavFile.size()-1);
wavFile.write((byte*)&sampleValue,2);
}
MIN_DATA_VALUE
和 MAX_DATA_VALUE
是您必须定义的内容。这一切都假设您正在使用整数数据。如果是 float ,则需要进行一些调整。
#include <SPI.h>
#include <SD.h>
int MIN_DATA_VALUE;
int MAX_DATA_VALUE;
File wavFile;
const char* filename = "data.wav";
/// The first 4 byte of a wav file should be the characters "RIFF" */
char chunkID[4] = {'R', 'I', 'F', 'F'};
/// 36 + SubChunk2Size
uint32_t chunkSize = 36; // You Don't know this until you write your data but at a minimum it is 36 for an empty file
/// "should be characters "WAVE"
char format[4] = {'W', 'A', 'V', 'E'};
/// " This should be the letters "fmt ", note the space character
char subChunk1ID[4] = {'f', 'm', 't', ' '};
///: For PCM == 16, since audioFormat == uint16_t
uint32_t subChunk1Size = 16;
///: For PCM this is 1, other values indicate compression
uint16_t audioFormat = 1;
///: Mono = 1, Stereo = 2, etc.
uint16_t numChannels = 1;
///: Sample Rate of file
uint32_t sampleRate = 44100;
///: SampleRate * NumChannels * BitsPerSample/8
uint32_t byteRate = 44100 * 2;
///: The number of byte for one frame NumChannels * BitsPerSample/8
uint16_t blockAlign = 2;
///: 8 bits = 8, 16 bits = 16
uint16_t bitsPerSample = 16;
///: Contains the letters "data"
char subChunk2ID[4] = {'d', 'a', 't', 'a'};
///: == NumSamples * NumChannels * BitsPerSample/8 i.e. number of byte in the data.
uint32_t subChunk2Size = 0; // You Don't know this until you write your data
void setup()
{
Serial.begin(9600);
while (!Serial);
if (!SD.begin(4))
while (1);
wavFile = SD.open(filename, FILE_WRITE);
if (!wavFile)
while (1);
writeWavHeader();
}
void loop()
{
int data = getSomeData();
writeDataToWavFile(data);
}
void writeWavHeader()
{
wavFile.seek(0);
wavFile.write(chunkID,4);
wavFile.write((byte*)&chunkSize,4);
wavFile.write(format,4);
wavFile.write(subChunk1ID,4);
wavFile.write((byte*)&subChunk1Size,4);
wavFile.write((byte*)&audioFormat,2);
wavFile.write((byte*)&numChannels,2);
wavFile.write((byte*)&sampleRate,4);
wavFile.write((byte*)&byteRate,4);
wavFile.write((byte*)&blockAlign,2);
wavFile.write((byte*)&bitsPerSample,2);
wavFile.write(subChunk2ID,4);
wavFile.write((byte*)&subChunk2Size,4);
}
void writeDataToWavFile(int data)
{
int16_t sampleValue = map(data, MIN_DATA_VALUE, MAX_DATA_VALUE,-32767,32767);
subChunk2Size += numChannels * bitsPerSample/8;
wavFile.seek(40);
wavFile.write((byte*)&subChunk2Size,4);
wavFile.seek(4);
chunkSize = 36 + subChunk2Size;
wavFile.write((byte*)&chunkSize,4);
wavFile.seek(wavFile.size()-1);
wavFile.write((byte*)&sampleValue,2);
}
总结
关于c++ - 如何将 Arduino 的模拟输入读数从草图转换为 .WAV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66484763/
我想获取下一页上首字母(“H”)周围框的坐标(以及与其他首字母类似的框,因此 opencv 模板匹配不是一个选项): 正在关注 this教程,我尝试用 opencv contours 解决问题: im
我正在 p5.js 中开发一个项目,我需要能够定义比我的浏览器窗口大得多的模糊 Canvas 尺寸。我本质上需要保持 p5js 像素大小(例如 3840px、1920px),但可以看到整个 Canva
是否可以将二进制数据文件与发送到 Arduino 时传输的 Arduino 草图一起添加?我设法在 IDE 中添加该文件并将其复制到我的项目文件夹中的“数据”目录,但我找不到在我的代码中访问它的方法。
我在处理中编写了自己的草图,并使用 processingjs 和 ajax 将其插入到页面中,如下所示: $.getScript("js/libs/processingjs.js", function
想象一下,我想做一个用户可以聊天的应用程序,但在视觉上 - 他们会在屏幕上画东西。屏幕会被分成两半,每个参与者都会在自己的一半上画一些东西,其他参与者会看到它。 在触摸屏上绘制草图应该非常简单,还可以
我正在尝试将创建的 Canvas 插入到 WordPress 中手动创建的页面模板的 div 元素中: 模板自定义.php 草图.js function setup() { var WI
我正在尝试学习硬件编程,并为此订购了 Arduino。当我等待它交付时,我开始四处寻找并遇到了 Fritzing 。我能够将 LED 连接到微 Controller 。我的问题是这样的: Fritzi
我正在尝试在同一页面上运行多个草图。 初始化脚本指定: /* * This code searches for all the * in your page and loads each scrip
我已经在 Processing 中编程一段时间了。 我还处理过形状和 SVG文件。 有关于 SVG 的卑微经验Processing 中的文件让我觉得在 P5.js 中也是一样的故事。 ,这显然不是这种
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 3年前关闭。 Improve this
我希望为我的动画工作室建立一个网站,我希望在后台设置一些 p5 草图以增加一些天赋。现在,我设置了两个基本草图,以确保一切正常。一个显示为 pink ,其中一个显示为 blue ,它们被设计为在“我们
编辑: 我做了更多研究并弄清楚了。将 html 位更改为: Volume: 0%100% (显然我也给了 Canvas 一个 id) 将功能更改为: void changeVolume(slideAm
对于我的生活,我无法想办法让这个草图以缓慢的速度运行,以清楚地看到移动的波浪图案。只是节奏快得让人抓狂。它使用一维柏林噪声。 let gap = 10; let start = 0; function
我想重新启动我链接到头部的样式和 processing.js 脚本,以便它们在通过 ajax 请求引入时正确显示。我看到此代码需要在 ajax 请求中的什么位置,但我不知道如何告诉代码简单地重新应用脚
我试图在单击时使用 ajax 加载 processing.js 草图,但它不起作用。如果我立即加载草图,它会起作用,但不会在用户交互时起作用。这是我的代码: $('#clicker').click(f
当我将 MSSymbolInstances 导出为 SVG 时,我总是在 SVG 代码中得到这一行。 直到我手动编辑上面的填充并将“#1D1F20”更改为“无”,我才能在我的程序中使用SVG。有什么
我正在尝试弄清楚是否可以从大查询中导出 hyperloglog 草图并在外部合并它们以进行基数估计。是否有可用的开源库可以轻松解析大型查询草图? 如果不是,是否有任何关于 biq 查询的 hyperl
如果我对 p5.js 草图有疑问,我如何将我的代码包含在问题中,以便查看问题的人可以快速测试我的代码以查看我正在尝试做什么或有什么问题? 我知道我可以使用 {} 工具栏按钮包含代码,该按钮使用 4 个
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我很幸运地使用 html 表单元素控制了 processing.js 草图,并且想使用 jQuery slider 来做同样的事情。 $(function() { $( "#slider-r
我是一名优秀的程序员,十分优秀!