1 #include <math.h>
2 #include <util/bmem.h>
3 #include <util/threading.h>
4 #include <util/platform.h>
5 #include <obs.h>
6
7 struct sinewave_data {
8 bool initialized_thread;
9 pthread_t thread;
10 os_event_t *event;
11 obs_source_t *source;
12 };
13
14 /* middle C */
15 static const double rate = 261.63 / 48000.0;
16
17 #ifndef M_PI
18 #define M_PI 3.1415926535897932384626433832795
19 #endif
20
21 #define M_PI_X2 M_PI * 2
22
sinewave_thread(void * pdata)23 static void *sinewave_thread(void *pdata)
24 {
25 struct sinewave_data *swd = pdata;
26 uint64_t last_time = os_gettime_ns();
27 uint64_t ts = 0;
28 double cos_val = 0.0;
29 uint8_t bytes[480];
30
31 while (os_event_try(swd->event) == EAGAIN) {
32 if (!os_sleepto_ns(last_time += 10000000))
33 last_time = os_gettime_ns();
34
35 for (size_t i = 0; i < 480; i++) {
36 cos_val += rate * M_PI_X2;
37 if (cos_val > M_PI_X2)
38 cos_val -= M_PI_X2;
39
40 double wave = cos(cos_val) * 0.5;
41 bytes[i] = (uint8_t)((wave + 1.0) * 0.5 * 255.0);
42 }
43
44 struct obs_source_audio data;
45 data.data[0] = bytes;
46 data.frames = 480;
47 data.speakers = SPEAKERS_MONO;
48 data.samples_per_sec = 48000;
49 data.timestamp = ts;
50 data.format = AUDIO_FORMAT_U8BIT;
51 obs_source_output_audio(swd->source, &data);
52
53 ts += 10000000;
54 }
55
56 return NULL;
57 }
58
59 /* ------------------------------------------------------------------------- */
60
sinewave_getname(void * unused)61 static const char *sinewave_getname(void *unused)
62 {
63 UNUSED_PARAMETER(unused);
64 return "Sinewave Sound Source (Test)";
65 }
66
sinewave_destroy(void * data)67 static void sinewave_destroy(void *data)
68 {
69 struct sinewave_data *swd = data;
70
71 if (swd) {
72 if (swd->initialized_thread) {
73 void *ret;
74 os_event_signal(swd->event);
75 pthread_join(swd->thread, &ret);
76 }
77
78 os_event_destroy(swd->event);
79 bfree(swd);
80 }
81 }
82
sinewave_create(obs_data_t * settings,obs_source_t * source)83 static void *sinewave_create(obs_data_t *settings, obs_source_t *source)
84 {
85 struct sinewave_data *swd = bzalloc(sizeof(struct sinewave_data));
86 swd->source = source;
87
88 if (os_event_init(&swd->event, OS_EVENT_TYPE_MANUAL) != 0)
89 goto fail;
90 if (pthread_create(&swd->thread, NULL, sinewave_thread, swd) != 0)
91 goto fail;
92
93 swd->initialized_thread = true;
94
95 UNUSED_PARAMETER(settings);
96 return swd;
97
98 fail:
99 sinewave_destroy(swd);
100 return NULL;
101 }
102
103 struct obs_source_info test_sinewave = {
104 .id = "test_sinewave",
105 .type = OBS_SOURCE_TYPE_INPUT,
106 .output_flags = OBS_SOURCE_AUDIO,
107 .get_name = sinewave_getname,
108 .create = sinewave_create,
109 .destroy = sinewave_destroy,
110 };
111