首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在c++中生成.au文件

在c++中生成.au文件
EN

Stack Overflow用户
提问于 2011-03-30 16:25:01
回答 4查看 406关注 0票数 2

出于病态的好奇心,我一直试图想出一个程序,它将产生一个4秒440A的C音符。然而,在VLC中播放输出的文件不会产生任何音乐。

使用维基百科作为这个页面上.au标题的指南:http://en.wikipedia.org/wiki/Au_file_format我想出了这个:

代码语言:javascript
复制
#include <stdio.h>
#include <math.h>

#define MAGIC_NUM 0x2e736e64
#define DEFAULT_OFFSET 24
#define UNKNOWN_SIZE 0xffffffff
#define BIT_32_PCM 5
#define STEREO 2
#define SAMPLE_RATE 8000
#define DURATION 4
#define MIDDLE_A 440

int main(int argc, char** argv) {
    FILE* sound;

    sound = fopen("output.au", "w");

    //write header
    fputc(MAGIC_NUM, sound);
    fputc(DEFAULT_OFFSET, sound);
    fputc(UNKNOWN_SIZE, sound);
    fputc(BIT_32_PCM, sound);
    fputc(SAMPLE_RATE, sound);
    fputc(STEREO, sound);

    //write a duration of a constant note
    int i;
    for(i = 0; i <= DURATION * SAMPLE_RATE; i++) {
        fputc((int)floor(MIDDLE_A * sin(i)), sound);
    }

    fclose(sound);

    return 0;
}

有人知道我做错了什么吗?

EN

回答 4

Stack Overflow用户

发布于 2011-03-30 16:35:39

您不希望文件以文本形式打开-它可能会对任何已编写的换行符做一些有趣的事情。

代码语言:javascript
复制
sound = fopen("output.au", "wb");

你不想写字符-使用fwrite而不是fputc

代码语言:javascript
复制
fwrite(".snd", 1, 4, sound);

还要注意,.au文件是高字节顺序的-如果你在x86或x86_64上,你的原生字节顺序是小字节顺序,你需要在写入数据之前转换数据。

票数 4
EN

Stack Overflow用户

发布于 2011-03-30 16:45:48

问题是fputc,它只输出一个字符。例如,您不能使用fputc一次编写MAGIC_NUM。一种解决方案是定义您自己的fput函数:

代码语言:javascript
复制
// write a word (2 bytes)
void fputw (unsigned int value, FILE* f)
{
    fputc(value & 0xff, f);
    fputc(value >> 8 & 0xff, f);
}

// write a dword (4 bytes)
void fputdw(unsigned int value, FILE* f)
{
    fputc(value & 0xff, f);
    fputc(value >> 8  & 0xff, f);
    fputc(value >> 16 & 0xff, f);
    fputc(value >> 24 & 0xff, f);
}

//write header
fputdw(MAGIC_NUM, sound);
fputdw(DEFAULT_OFFSET, sound);
fputdw(UNKNOWN_SIZE, sound);
fputdw(BIT_32_PCM, sound);
fputdw(SAMPLE_RATE, sound);
fputdw(STEREO, sound);
票数 1
EN

Stack Overflow用户

发布于 2011-03-30 21:39:35

关于一次写一个字符的评论是针对这个问题的,但这里还有更根本的问题--

  1. sin()函数的输出是一个范围在-1.0之间的浮点数。+1.0;然后取其下限,它将始终为零。
  2. 该正弦发生器的每个样本的输出需要从浮点型转换为32位整数。
  3. 您需要以不同的方式转换样本位置--您需要计算正弦波在样本之间前进的角频率(以弧度为单位)。

伪代码类似(未测试...)

代码语言:javascript
复制
SAMPLE_RATE = 44100.0
FREQ = 440.0
PI = 3.14159
DURATION = 4
AMPLITUDE = 1.0

ANGULAR_FREQ = (2 * PI * FREQ) / SAMPLE_RATE

for (int i = 0; i < (int) DURATION * SAMPLE_RATE; ++i)
{
    // get sample value in range -1.0 .. + 1.0
    floatSample = AMPLITUDE * sin(i * ANGULAR_FREQ)
    // convert to correctly scaled integer representation
    intSample = (int) floor(0x7FFFFFFF * floatSample);
    // write to file, send out DAC, whatever...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5483816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档