Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/wavplay/wavplay.c
1072 views
1
#include "irc.h"
2
#include "struct.h"
3
#include "ircaux.h"
4
#include "module.h"
5
#define INIT_MODULE
6
#include "modval.h"
7
8
#include <sys/ioctl.h>
9
#include <sys/mman.h>
10
#include <sys/stat.h>
11
#include <unistd.h>
12
13
#ifdef HAVE_MACHINE_SOUNDCARD_H
14
#include <machine/soundcard.h>
15
#elif defined(HAVE_LINUX_SOUNDCARD_H)
16
#include <linux/soundcard.h>
17
#elif defined(HAVE_SYS_SOUNDCARD_H)
18
#include <sys/soundcard.h>
19
#else
20
#define NO_SOUNDCARD_H
21
#endif
22
#ifndef NO_SOUNDCARD_H
23
static int dspfd = -1;
24
#define WAV_RIFF_MAGIC "RIFF"
25
#define WAV_WAVE_MAGIC "WAVE"
26
#define WAV_FMT_MAGIC "fmt "
27
#define WAV_DATA_MAGIC "data"
28
29
typedef struct {
30
unsigned char riffID[4];
31
unsigned long riffsize;
32
unsigned char waveID[4];
33
unsigned char fmtID[4];
34
unsigned long fmtsize;
35
unsigned short w_formattag;
36
unsigned short n_channels;
37
unsigned long n_samples;
38
unsigned long avg_bytes;
39
unsigned short n_blockalign;
40
unsigned short w_bitssample;
41
unsigned char dataID[4];
42
unsigned long n_datalen;
43
} Wave_Header;
44
45
char *validate_wav_header(char *header)
46
{
47
Wave_Header *w = (Wave_Header *)header;
48
49
if (strncmp(w->riffID, WAV_RIFF_MAGIC, 4))
50
return NULL;
51
52
if (strncmp(w->waveID, WAV_WAVE_MAGIC, 4))
53
return NULL;
54
55
if (strncmp(w->fmtID, WAV_FMT_MAGIC, 4))
56
return NULL;
57
58
if (w->fmtsize != 16)
59
return NULL;
60
61
#if 0
62
if (w->w_formattag != 1)
63
return NULL;
64
65
if (w->n_channels != 2 && w->n_channels != 1)
66
return NULL;
67
#endif
68
69
if (strncmp(w->dataID, WAV_DATA_MAGIC, 4))
70
return(NULL);
71
return (header + sizeof(Wave_Header));
72
}
73
74
75
int open_dsp(Wave_Header *wav_info)
76
{
77
int arg;
78
79
if ((dspfd = open("/dev/dsp",O_WRONLY)) < 0)
80
return -1;
81
arg = wav_info->w_bitssample;
82
if ((ioctl(dspfd, SOUND_PCM_WRITE_BITS, &arg)) == -1)
83
return -1;
84
85
arg = wav_info->n_channels; /* mono or stereo */
86
if ((ioctl(dspfd, SOUND_PCM_WRITE_CHANNELS, &arg)) == -1)
87
return -1;
88
89
arg = wav_info->n_samples; /* sampling rate */
90
if ((ioctl(dspfd, SOUND_PCM_WRITE_RATE, &arg)) == -1)
91
return -1;
92
return dspfd;
93
}
94
95
int play_buffer(int dspfd, short *start, short *end)
96
{
97
int status;
98
99
status = write(dspfd,(char *)start,(char *)end - (char *)start);
100
101
if (status != (char *)end - (char *)start)
102
return -1;
103
return 0;
104
}
105
106
void wave_play_file(int wavfd, int dspfd, short *current, short *audioend, int interval)
107
{
108
while (current < audioend)
109
{
110
short *endcurrent = current + interval;
111
112
if (endcurrent > audioend)
113
endcurrent = audioend;
114
if (play_buffer(dspfd,current,endcurrent) == -1)
115
endcurrent = audioend;
116
current = endcurrent;
117
}
118
}
119
120
BUILT_IN_DLL(wav_play)
121
{
122
char *filename = NULL;
123
124
if (dspfd != -1)
125
{
126
put_it("Already playing a .wav file");
127
return;
128
}
129
if ((filename = next_arg(args, &args)))
130
{
131
char *inwavbuf;
132
short *current;
133
short *audioend;
134
short *audio;
135
Wave_Header *wav_info;
136
int wavfd;
137
struct stat input_fstat;
138
size_t interval;
139
140
if ((wavfd = open(filename,O_RDONLY)) == -1)
141
{
142
put_it("errno %s", strerror(errno));
143
return;
144
}
145
if (fstat(wavfd,&input_fstat) != 0)
146
return;
147
if (input_fstat.st_size < sizeof(Wave_Header))
148
return;
149
if (!(inwavbuf = mmap(NULL, input_fstat.st_size, PROT_READ, MAP_SHARED, wavfd, 0)))
150
return;
151
152
if (!(audio = (short *)validate_wav_header(inwavbuf)))
153
{
154
put_it("Invalid wav file");
155
return;
156
}
157
current = audio;
158
wav_info = (Wave_Header *)inwavbuf;
159
audioend = (short *)((char *)audio + wav_info->n_datalen);
160
161
if ((dspfd = open_dsp(wav_info)) == -1)
162
{
163
close(wavfd);
164
munmap(inwavbuf, input_fstat.st_size);
165
return;
166
}
167
interval = (size_t )((double )wav_info->n_samples * 0.1 * 2);
168
if (!fork())
169
{
170
wave_play_file(wavfd, dspfd, current, audioend, interval);
171
munmap(inwavbuf,input_fstat.st_size);
172
close(wavfd);
173
close(dspfd);
174
dspfd = -1;
175
_exit(1);
176
}
177
munmap(inwavbuf,input_fstat.st_size);
178
close(wavfd);
179
close(dspfd);
180
dspfd = -1;
181
}
182
}
183
184
185
186
int Wavplay_Init(IrcCommandDll **intp, Function_ptr *global_table)
187
{
188
initialize_module("wavplay");
189
add_module_proc(COMMAND_PROC, "Wavplay", "wavplay", NULL, 0, 0, wav_play, NULL);
190
bitchsay("Wavplay Module loaded. /wavplay <filename>");
191
return 0;
192
}
193
#endif
194
195