В том, что одновременно играются - да. Я менял частоту и это было слышно.
1 - номер канала
440 - частота
180 - время игры, 10 секунд (18 тиков = 1 сек.)
Всё остальное мне непонятно, это уже вам разбираться.
Можете модифицировать подсказку, чтобы выводился пример с обозначением параметров. И ещё, можно заменить функцию strcmp() на strcmpi(), чтобы регистр букв не проверялся при сравнивании, а то при вводе строчными, программа говорит вы, что-то не то вводите.
Также, если Borland выдаёт предупреждение о несоответствии переменных, можно сделать так
unsigned div = (unsigned)(1193180L / current_freq);
А для информативности, можно добавить, пояснения:
// Голос 1
play_voice(
a1,// канал
b1,// частота
c1 // время игры
);
В общем, вот, прикладываю один текст
Развернуть: Main.cpp- Код: Выделить всё
// Main.cpp
//
// Программа реализует двухканальный псевдополифонический бипер, два
// логических процесса или голоса, играющих разные ноты одновременно
// за счет перехвата системного таймера Irq 0, Int 8.
// Звук воспроизведения через динамик ПК (PC Speaker).
//
// Программа получает параметры из командной строки.
// Пример запуска:
// POLYPHON /A 1 440 180 /B 2 554 180
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
// Старый вектор прерывания таймера.
void interrupt (*old_timer)(...);
// Структура для процесса, голоса воспроизведения.
typedef struct {
unsigned long duration; // Длительность в тиках таймера.
unsigned long frequency;// Частота звука Гц.
unsigned long counter;// Текущий счетчик смены фазы.
int active; // Флаг активности канала.
} Voice;
Voice voice1 = {0, 0, 0, 0};
Voice voice2 = {0, 0, 0, 0};
// Текущая, выводимая частота на динамик.
unsigned long current_freq;
int toggle_channel;
void interrupt new_timer(...)
{
// Функция, устанавливает новое прерывание таймера,
// вызывается 18.2 раза в секунду или чаще при перенастройке.
// Вызвать оригинальный, системный обработчик DOS,
// чтобы часы не отставали.
old_timer();
// Чередование каналов.
if (voice1.active && voice2.active) {
toggle_channel = !toggle_channel;
current_freq = toggle_channel ? voice1.frequency : voice2.frequency;
}
else if (voice1.active)
current_freq = voice1.frequency;
else if (voice2.active)
current_freq = voice2.frequency;
else
current_freq = 0;
// Управление динамиком.
if (current_freq > 0)
{
unsigned div = (unsigned)(1193180L / current_freq);
outportb(0x43, 0xB6); // Канал 2, режим 3, меандр.
outportb(0x42, div & 0xFF);
outportb(0x42, div >> 8);
// Включить динамик, биты 0 и 1 порта 0x61
outportb(0x61, inportb(0x61) | 3);
}
else
{
// Выключить динамик.
outportb(0x61, inportb(0x61) & 0xFC);
}
// Уменьшить счетчики длительности.
if (voice1.active)
{
if (--voice1.duration == 0)
voice1.active = 0;
}
if (voice2.active)
{
if (--voice2.duration == 0)
voice2.active = 0;
}
}
void play_voice(int channel, unsigned long freq, unsigned long dur)
{
// Функция запуска ноты
// в первом или втором процессе...
disable(); // Запретить прерывания при изменении общей структуры.
if (1 == channel)
{
voice1.frequency = freq;
voice1.duration = dur;
voice1.active = 1;
}
else
{
voice2.frequency = freq;
voice2.duration = dur;
voice2.active = 1;
}
enable();
}
const char* MakeAppname(char* argv) {
static char Exename[128];
if (!Exename[0]) {
strcpy(Exename,argv);
char* svPath=Exename;
char* svName=Exename;
do {
if ('\\'==*svPath||'/'==*svPath)
svName=svPath+1;
} while (*svPath++);
strcpy(Exename,svName);
if (strchr(Exename,'.'))
*strchr(Exename,'.')=0;
} return Exename;
}
void Examples(char* argv) {
printf("%s /A 1 440 180 /B 2 554 180\n", MakeAppname(argv));
exit(0);
}
void Usage(char* argv) {
printf(" Usage: %s [/A 1 440 180] [/B 2 554 180]\n",
MakeAppname(argv));
printf(" [/EXAMPLES]\n");
exit(0);
}
int main(int argc, char* argv[]) {
if (argc<2)
Usage(argv[0]);
int a1, b1, c1;
int a2, b2, c2;
a1 = b1 = c1 = 0;
a2 = b2 = c2 = 0;
for (int x=1; x<argc; ++x) {
if ('/' == argv[x][0] ||
'-' == argv[x][0]) {
if ('A' == argv[x][1] ||
'a' == argv[x][1]) {
if (x + 3 < argc) {
a1 = atoi(argv[x + 1]);
b1 = atoi(argv[x + 2]);
c1 = atoi(argv[x + 3]);
x += 3;
} else {
printf("Missing argument for /A\n");
Usage(argv[0]);
return 0;
}
} else if ('B' == argv[x][1] ||
'b' == argv[x][1]) {
if (x + 3 < argc) {
a2 = atoi(argv[x + 1]);
b2 = atoi(argv[x + 2]);
c2 = atoi(argv[x + 3]);
x += 3;
} else {
printf("Missing argument for /B\n");
Usage(argv[0]);
return 0;
}
} else if (0 == strcmpi(argv[x], "/EXAMPLES")) {
Examples(argv[0]);
return 0;
} else {
printf("Bad option: \"%s\"\n",argv[x]);
Usage(argv[0]);
return 0;
}
} else {
printf("Bad argument: \"%s\"\n",argv[x]);
Usage(argv[0]);
return 0;
}
}
clrscr();
printf("PC Speaker Ї®«Ёд®Ёп. „«п ўл室 , ¦¬ЁвҐ «оЎго Є« ўЁиг...\n");
// Сохранить старый и установить новый
// обработчик прерывания таймера.
old_timer = getvect(8);
setvect(8, new_timer);
// Параллельный запуск двух разных частот полифонии.
// Голос 1
play_voice(
a1,// канал
b1,// частота
c1 // время игры
);
//play_voice(1, 440, 180); // 1 канал, 440 Гц, нота Ля, Играть 10 секунд, 18 тиков = 1 сек.
// Голос 2
play_voice(a2, b2, c2);
//play_voice(2, 554, 180); // 2 канал, 554 Гц, нота До-диез, Играть 10 секунд
// Ожидание нажатия клавиши...
while (!kbhit())
{
// Цикл программы...
}
getch();
// Восстановить системный таймер и выключить звук.
setvect(8, old_timer);
outportb(0x61, inportb(0x61) & 0xFC);
return 0;
}