aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/jitter.c
blob: 865438bf81cb60f8b98b1953247cb9735417f4dc (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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* Jitter buffering functions
 *
 * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
 * All Rights Reserved
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include "sample.h"
#include "debug.h"
#include "jitter.h"

/* create jitter buffer */
int jitter_create(jitter_t *jitter, int length)
{
	memset(jitter, 0, sizeof(*jitter));
	jitter->spl = calloc(length * sizeof(sample_t), 1);
	if (!jitter->spl) {
		PDEBUG(DDSP, DEBUG_ERROR, "No memory for jitter buffer.\n");
		return -ENOMEM;
	}
	jitter->len = length;

	return 0;
}

void jitter_destroy(jitter_t *jitter)
{
	if (jitter->spl) {
		free(jitter->spl);
		jitter->spl = NULL;
	}
}

/* store audio in jitterbuffer
 *
 * stop if buffer is completely filled
 */
void jitter_save(jitter_t *jb, sample_t *samples, int length)
{
	sample_t *spl;
	int inptr, outptr, len, space;
	int i;

	spl = jb->spl;
	inptr = jb->inptr;
	outptr = jb->outptr;
	len = jb->len;
	space = (outptr - inptr + len - 1) % len;

	if (space < length)
		length = space;
	for (i = 0; i < length; i++) {
		spl[inptr++] = *samples++;
		if (inptr == len)
			inptr = 0;
	}

	jb->inptr = inptr;
}

/* get audio from jitterbuffer
 */
void jitter_load(jitter_t *jb, sample_t *samples, int length)
{
	sample_t *spl;
	int inptr, outptr, len, fill;
	int i, ii;

	spl = jb->spl;
	inptr = jb->inptr;
	outptr = jb->outptr;
	len = jb->len;
	fill = (inptr - outptr + len) % len;

	if (fill < length)
		ii = fill;
	else
		ii = length;

	/* fill what we got */
	for (i = 0; i < ii; i++) {
		*samples++ = spl[outptr++];
		if (outptr == len)
			outptr = 0;
	}
	/* on underrun, fill with silence */
	for (; i < length; i++) {
		*samples++ = 0;
	}

	jb->outptr = outptr;
}

void jitter_clear(jitter_t *jb)
{
	jb->inptr = jb->outptr = 0;
}