Доброго времени суток, сообщество!Не ходя вокруг да около: возникла задача написания генератора сигналов кода Морзе. С работой со звуком доселе вообще не сталкивался (исключая использования SDL). Покопавшись в исходниках без проблем разобрался как работать с OSS (open/write). Однако возник ряд вопросов:
- записываем мы в устройство обычным вызовом write(2), из некоторого буфера данные. На основании чего устройство определяет с какой "скоростью" их воспроизводить? Предположу, что частота дискретизации (или как она называется), которая выставляется ioctl(fd, SNDCTL_DSP_SPEED) ?!- наиболее интересный и загадочный для меня вопрос - как "сгенерить" необходимый мне сигнал, хотя бы в wav формате. При этом как минимум необходимо обучить программу генерить сигнал "точка", "тире" с различной длительностью + "сигнал пауза" (тоже с произвольной длительностью).
ps+0x0: думаю, наблюдается некоторая сумбурность изложения, но это скорее от незнания вопроса :(
ps+0x1: документация и другие подзатыльники приветсвуются :)
Документация по OSS:
>Документация по OSS:
>
>http://www.opensound.com/pguide/index.htmlогромное спасибо!!! В принципе в большинстве своих предположений я был прав.
Однако для меня до сих пор остается не ясным вопрос - генерации самих сигналов. Опишу чуть подробнее:
Стандартным соотношением для точка/тире является 1/3. Т.е. допустим, если длительность звучания точки 1 с. , то тире будет длиться 3-и сек. Для "кодирования" буквы используются точки + тире + небольшие временные задержки между ними, равными длительности точки. Допустим,
А : . -Между символами используется иная задержка. Так вот нужно иметь как минимум 3-и функции для генерации данных сигналов в виде "писков", а не "белого шума" + чтобы они в качестве параметра принимали длительность точки (т.к. на основании ее и будет произвоиться длительность все сигналов).
НО... все это замечательно и прекрасно, пока дело не доходит до реализации - как быть? Я так понимаю нужно сгенерить синусоидальный сигнал (ведь именно его слышит наше ухо?!) с заданными параметрами. Соотвественно вопрос, как расчитать эти параметры, в учетом sample rate. Возможно, по этому вопросу есть какое-нибудь описалово (мне, к сожалению, не удалось найти) ?
ps: задача упрощается в результате использования mono сигнала на выходе - программа создается не для adv радистов :), которые способны на 3-и канала работать, а для начинающих.
Самый простой вариант:Можно взять два крайних значения синуса (-1, 1) и выводить их поочереди. Попробуйте откомпилять следующий код:
/* sin.c */
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>int main()
{ unsigned char c1=0, c2=255;
int format=AFMT_U8; /* формат сэмплов: U - беззнаковые значения, 8 - 8 бит на сэмпл */
int rate=2000;
int channels=1;ioctl(1, SNDCTL_DSP_SETFMT, &format);
ioctl(1, SNDCTL_DSP_CHANNELS, &channels);
ioctl(1, SNDCTL_DSP_SPEED, &rate);while(1)
{ write(1, &c1, 1);
write(1, &c2, 1);
}
return 0;
}и выполнить
$ sin >/dev/dsp
Когда надоест нажмите ^C :)
Теперь поиграйтесь со значениями rate и получите разные частоты (то есть разную высоту звука).Для паузы необходимо выводить нули (или в случае unsigned 8 bit, как описано выше - 128).
То есть примерно так:
/* space.c */
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>int main()
{ unsigned char c=128;
int format=AFMT_U8;
int rate=2000;
int channels=1;ioctl(1, SNDCTL_DSP_SETFMT, &format);
ioctl(1, SNDCTL_DSP_CHANNELS, &channels);
ioctl(1, SNDCTL_DSP_SPEED, &rate);while(1)
write(1, &c, 1);
return 0;
}То есть команда
$ space >/dev/dsp
Выведет на вашу звуковую карту полную тишину :)Для задания длительности вывода звука и частоты дескритизации используйте простой рассчёт:
rate=<частота звука>*2 (2 сэмпла в одном периоде синуса)
N=<необходимая длительность>*<частота звука> - именно столько пар (для "синуса") отсчётов нужно вывести.Окультурить это всё в виде функций - дело 2-х минут...
Удачи!
btw: Именно так работает PC-speaker.
>btw: Именно так работает PC-speaker.огромное спасибо!!!! ЭТО то что нужно!!!