summaryrefslogtreecommitdiffstats
path: root/src/spatial.c
blob: 809fce1bd776762069574c4fc353f33c95e6c3ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <xas/spatial.h>

static inline float dist(xas_spatial_coord a, xas_spatial_coord b) {
    return powf(powf(b.x - a.x, 2.0f)
              + powf(b.y - a.y, 2.0f)
              + powf(b.z - a.z, 2.0f), 0.5f);
}

static int buf_realloc(xas_spatial_scene *scene, void *buf) {
    float width = scene->observer.width,
          speed = scene->speed;

    size_t sample_rate = scene->format.sample_rate,
           stride      = scene->format.channels * scene->format.sample_size,
           count       = floorf(width / (speed / sample_rate));

    if ((buf = realloc(buf, stride * count)) == NULL) {
        goto error_realloc;
    }

    scene->buf    = buf;
    scene->buflen = count;

    return 0;

error_realloc:
    return -1;
}

xas_spatial_scene *xas_spatial_scene_new(xas_audio_format format,
                                             xas_spatial_coord speaker_l,
                                             xas_spatial_coord speaker_r) {
    xas_spatial_scene *scene;

    if ((scene = malloc(sizeof(*scene))) == NULL) {
        goto error_malloc_scene;
    }

    memset(scene, '\0', sizeof(*scene));

    scene->format    = format;
    scene->speaker_l = speaker_l;
    scene->speaker_r = speaker_r;
    scene->speed     = XAS_SPATIAL_DEFAULT_SPEED;

    if (buf_realloc(scene, NULL) < 0) {
        goto error_buf_realloc;
    }

    return scene;

error_buf_realloc:
    free(scene);

error_malloc_scene:
    return NULL;
}

void xas_spatial_scene_destroy(xas_spatial_scene *scene) {
    free(scene->buf);
    free(scene);
}

int xas_spatial_scene_set_observer(xas_spatial_scene *scene,
                                      xas_spatial_coord coord,
                                      xas_spatial_rotation rotation,
                                      float width) {
    scene->observer.coord    = coord;
    scene->observer.rotation = rotation;
    scene->observer.width    = width;

    return buf_realloc(scene, scene->buf);
}

void xas_spatial_scene_set_speaker_coords(xas_spatial_scene *scene,
                                            xas_spatial_coord speaker_l,
                                            xas_spatial_coord speaker_r) {
    scene->speaker_l = speaker_l;
    scene->speaker_r = speaker_r;
}

void xas_spatial_scene_set_speed(xas_spatial_scene *scene, float speed) {
    scene->speed = speed;
}