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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
samples.h
Sound device for sample playback.
***************************************************************************/
#pragma once
#ifndef __SAMPLES_H__
#define __SAMPLES_H__
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_SAMPLES_CHANNELS(_channels) \
samples_device::static_set_channels(*device, _channels);
#define MCFG_SAMPLES_NAMES(_names) \
samples_device::static_set_samples_names(*device, _names);
typedef device_delegate<void ()> samples_start_cb_delegate;
#define SAMPLES_START_CB_MEMBER(_name) void _name()
#define MCFG_SAMPLES_START_CB(_class, _method) \
samples_device::set_samples_start_callback(*device, samples_start_cb_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner)));
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> samples_device
class samples_device : public device_t,
public device_sound_interface
{
public:
// construction/destruction
samples_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void static_set_channels(device_t &device, UINT8 channels) { downcast<samples_device &>(device).m_channels = channels; }
static void static_set_samples_names(device_t &device, const char *const *names) { downcast<samples_device &>(device).m_names = names; }
static void set_samples_start_callback(device_t &device, samples_start_cb_delegate callback) { downcast<samples_device &>(device).m_samples_start_cb = callback; }
// getters
bool playing(UINT8 channel) const;
UINT32 base_frequency(UINT8 channel) const;
// start/stop helpers
void start(UINT8 channel, UINT32 samplenum, bool loop = false);
void start_raw(UINT8 channel, const INT16 *sampledata, UINT32 samples, UINT32 frequency, bool loop = false);
void pause(UINT8 channel, bool pause = true);
void stop(UINT8 channel);
void stop_all();
// dynamic control
void set_frequency(UINT8 channel, UINT32 frequency);
void set_volume(UINT8 channel, float volume);
// helpers
struct sample_t
{
// shouldn't need a copy, but in case it happens, catch it here
sample_t &operator=(const sample_t &rhs) { assert(false); return *this; }
UINT32 frequency; // frequency of the sample
std::vector<INT16> data; // 16-bit signed data
};
static bool read_sample(emu_file &file, sample_t &sample);
// interface
UINT8 m_channels; // number of discrete audio channels needed
const char *const *m_names; // array of sample names
samples_start_cb_delegate m_samples_start_cb; // optional callback
protected:
// subclasses can do it this way
samples_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_post_load();
// device_sound_interface overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal classes
struct channel_t
{
sound_stream * stream;
const INT16 * source;
INT32 source_length;
INT32 source_num;
UINT32 pos;
UINT32 frac;
UINT32 step;
UINT32 basefreq;
bool loop;
bool paused;
};
// internal helpers
static bool read_wav_sample(emu_file &file, sample_t &sample);
static bool read_flac_sample(emu_file &file, sample_t &sample);
void load_samples();
// internal state
std::vector<channel_t> m_channel;
std::vector<sample_t> m_sample;
// internal constants
static const UINT8 FRAC_BITS = 24;
static const UINT32 FRAC_ONE = 1 << FRAC_BITS;
static const UINT32 FRAC_MASK = FRAC_ONE - 1;
};
// iterator, since lots of people are interested in these devices
typedef device_type_iterator<&device_creator<samples_device>, samples_device> samples_device_iterator;
// ======================> samples_iterator
class samples_iterator
{
public:
// construction/destruction
samples_iterator(samples_device &device)
: m_samples(device),
m_current(-1) { }
// getters
const char *altbasename() const { return (m_samples.m_names != NULL && m_samples.m_names[0] != NULL && m_samples.m_names[0][0] == '*') ? &m_samples.m_names[0][1] : NULL; }
// iteration
const char *first()
{
if (m_samples.m_names == NULL || m_samples.m_names[0] == NULL)
return NULL;
m_current = 0;
if (m_samples.m_names[0][0] == '*')
m_current++;
return m_samples.m_names[m_current++];
}
const char *next()
{
if (m_current == -1 || m_samples.m_names[m_current] == NULL)
return NULL;
return m_samples.m_names[m_current++];
}
// counting
int count()
{
int save = m_current;
int result = 0;
for (const char *scan = first(); scan != NULL; scan = next())
result++;
m_current = save;
return result;
}
private:
// internal state
samples_device &m_samples;
int m_current;
};
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
extern const device_type SAMPLES;
#endif
|