File: tonegen.c

package info (click to toggle)
rat 4.2.20-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 2,888 kB
  • ctags: 3,655
  • sloc: ansic: 36,042; sh: 3,481; tcl: 2,740; makefile: 293
file content (154 lines) | stat: -rw-r--r-- 4,456 bytes parent folder | download | duplicates (5)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * FILE:    tonegen.c
 * PROGRAM: RAT
 * AUTHORS: Orion Hodson
 *
 * Copyright (c) 1999-2001 University College London
 * All rights reserved.
 */
 
#ifndef HIDE_SOURCE_STRINGS
static const char cvsid[] = 
	"$Id: tonegen.c,v 1.6 2001/01/08 20:30:10 ucaccsp Exp $";
#endif /* HIDE_SOURCE_STRINGS */

#include "config_unix.h"
#include "config_win32.h"
#include "debug.h"
#include "memory.h"
#include "util.h"

#include "ts.h"
#include "audio_types.h"
#include "pdb.h"
#include "mix.h"
#include "sndfile.h"
#include "codec_types.h"
#include "codec.h"
#include "converter_types.h"
#include "converter.h"

#include "tonegen.h"

#define TONEGEN_MAGIC 0xdeebfeed

struct s_tonegen {
        struct s_mixer     *ms;
        pdb_t              *pdb;
        pdb_entry_t        *pdbe;       /* spoof participant                 */
        timestamp_t                write_end;  /* last time played                  */
        uint8_t             played;     /* initialized indicator             */
        uint16_t            tonefreq;
        uint16_t            toneamp;
        uint32_t            magic;
};

static const uint32_t TONEGEN_SSRC_ID = 0xefff0fff; /* 1 in 4 billion */

int  
tonegen_create  (tonegen_t          **ppt, 
                 struct s_mixer     *ms, 
                 struct s_pdb       *pdb, 
                 uint16_t            tonefreq,
                 uint16_t            toneamp)
{
        tonegen_t           *pt;
        pdb_entry_t         *pdbe;

        if (pdb_item_create(pdb, 8000, TONEGEN_SSRC_ID) == FALSE ||
            pdb_item_get(pdb, TONEGEN_SSRC_ID, &pdbe) == FALSE) {
                debug_msg("tonegen could not create spoof participant\n");
                return FALSE;
        }
        
        pt  = (tonegen_t*)xmalloc(sizeof(tonegen_t));
        if (pt == NULL) {
                debug_msg("Could not allocate tonegen\n");
                return FALSE;
        }

        *ppt          = pt;
        pt->ms        = ms;
        pt->pdb       = pdb;
        pt->pdbe      = pdbe;
        pt->played    = 0;
        pt->magic     = TONEGEN_MAGIC;
        pt->toneamp   = toneamp;
        pt->tonefreq  = tonefreq;

        return TRUE;
}

void 
tonegen_destroy(tonegen_t **ppt)
{
        tonegen_t *pt;

        pt = *ppt;
        assert(pt->magic == TONEGEN_MAGIC);

        pdb_item_destroy(pt->pdb, TONEGEN_SSRC_ID);

        xfree(pt);
        *ppt = NULL;
}

int 
tonegen_play(tonegen_t *pt, timestamp_t start, timestamp_t end)
{
        timestamp_t                delta, duration;
        uint32_t            samples, phase, i;
        coded_unit          src;
        const mixer_info_t *mi; 
        sample             *buf;

        assert(ts_gt(start, end) == FALSE);

        if (pt->played == 0) {
                pt->write_end = end;
                pt->played    = 1;
        }

        delta = ts_sub(pt->write_end, end);
        duration = ts_map32(8000, 1280);
        if (!ts_gt(duration, delta)) {
                /* No audio needs putting into mixer but return TRUE to */
                /* indicate still active thought.                       */
                return TRUE;
        }

        mi = mix_query(pt->ms);

        duration       = ts_convert(mi->sample_rate, duration);
        samples        = duration.ticks * mi->channels; 

        /* Initialize src for reading chunk of sound file */
        src.id        = codec_get_native_coding(mi->sample_rate, mi->channels);
        src.state     = NULL;
        src.state_len = 0;
        src.data_len  = sizeof(sample) * samples;
        src.data      = (u_char*)block_alloc(src.data_len);

        buf = (sample*)src.data;
        phase = pt->write_end.ticks;
        if (mi->channels == 1) {
                for(i = 0; i < samples; i++) {
                        double t = pt->toneamp * sin(2 * M_PI * (phase + i) * pt->tonefreq / mi->sample_rate);
                        buf[i]   = (sample)t;
                }
        } else {
                for(i = 0; i < samples; i++) {
                        uint32_t j = i / mi->channels;
                        double t   = pt->toneamp * sin(2 * M_PI * (phase + j) * pt->tonefreq / mi->sample_rate);
                        buf[i]     = (sample)t;
                }
        }

        xmemchk();
        mix_put_audio(pt->ms, pt->pdbe, &src, pt->write_end);
        codec_clear_coded_unit(&src);
        pt->write_end = ts_add(pt->write_end, duration);

        return TRUE;
}