c++ 如何在linux下使用PC音箱?

eivnm1vs  于 2022-12-15  发布在  Linux
关注(0)|答案(6)|浏览(230)

如何在linux下使用PC扬声器进行C/C++编程?我可以控制哔哔声的时间和频率吗?

4ktjp1zp

4ktjp1zp1#

取自here

#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/kd.h>
int main(void)
{
    int freq[] = { /* C   D    E    F    G    A    B    C */
                    523, 587, 659, 698, 784, 880, 988, 1046 };
    int i;

    for (i=0; i<8; i++)
    {
            ioctl(STDOUT_FILENO, KIOCSOUND, 1193180/freq[i]);
            usleep(500000);
    }
    ioctl(STDOUT_FILENO, KIOCSOUND, 0); /*Stop silly sound*/
    return 0;
}
s3fp2yjn

s3fp2yjn2#

可以,打开一个控制台设备(例如/dev/console或/dev/tty 0),然后向其发出KIOCSOUND ioctl命令,如console_ioctl(4)手册页中所述。
这是令人厌恶的和Linux特有的,但我认为它回答了你的问题。
编辑:难以置信的是,ALSA的内核中有一个PC扬声器驱动程序,它可以让你在PC扬声器中播放数字声音。它的音质会很差,而且会占用很多CPU:)

bgibtngc

bgibtngc3#

如果您 * 真的 * 想这样做,请查看beep命令的源代码:http://www.johnath.com/beep/beep.c

wr98u20j

wr98u20j4#

如果芯片组中仍然有一个8253等效物连接到类似扬声器的东西,您可以根据数据表寄存器或古老的PC指南(我很欣慰地承认,我的头脑中不再有这些信息)从内核模块或以root身份调用ioperm()后访问它。
曾经也有一个内核PWM“模拟”音频驱动程序用于PC扬声器。我相信那是我第一次编译内核。那是在内核模块出现之前,或者至少是在它们进入流行发行版之前。

7fyelxc5

7fyelxc55#

在我使用Ubuntu 16.04的情况下,“ioctl”函数不起作用。
所以,最后,下面的代码在没有安装任何附加库的情况下运行良好。

/* This outputs a tone to the speaker */

#include <alsa/asoundlib.h>
#include <math.h>

#define RATE 44100 // PCM rate [Hz]
#define FREQ 440 // Tone frequence [Hz]
#define DURATION 5 // Tone duration [s]

void info_format(snd_pcm_format_t format);

int main(void)
{
    snd_pcm_t *handle;
    unsigned char buffer[RATE * DURATION];

    for (int i = 0; i < sizeof(buffer); i++)
    {
        buffer[i] = 0xFF * sin(2 * M_PI * FREQ * i / RATE);
    }

    snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0 /* blocked mode */);

    snd_pcm_set_params(handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1 /* channels */, RATE /* rate [Hz] */, 1 /* soft resample */, 500000 /* latency [us] */);

    snd_pcm_writei(handle, buffer, sizeof(buffer));

    snd_pcm_close(handle);

    return 0;
}

字符串
如果代码的文件名为“beep.c”,则可按如下方式编译:
gcc哔声. c-激光声-lm -o哔声
并且可以如下执行:
./哔声

f4t66c6m

f4t66c6m6#

计时器甚至存在于现代系统中的地址0x41 .. 0x43和0x61上。(我在Forth中有代码,运行在8核AMD的MSI主板上)。使用0x65 ioperm系统调用(允许解锁端口)并以root权限运行解决了玩音阶的罗塞塔代码挑战。

  • 必须使用unlock系统调用使端口0x41 0x42 0x43和0x62可访问

将0xB6存储到地址0x43(解锁定时器)
将频率的低字节设置为0x42,然后设置高字节。(选择例如2000作为频率)
通过将3存储到端口0x61开始发出蜂鸣声
这是玩音阶的罗塞塔代码挑战。Musical_scale
Forth代码是最具启发性的。

相关问题