52
52
#define SOUND_EXPR_FX_STEPS_OFFSET (40)
53
53
#define SOUND_EXPR_FX_STEPS_LENGTH (4)
54
54
55
- #define SOUND_EXPR_ENCODE_VOLUME (v ) ((v) * 1023 / 255)
56
- #define SOUND_EXPR_DECODE_VOLUME (v ) ((v) * 255 / 1023)
55
+ #define SOUND_EXPR_ENCODE_VOLUME (v ) ((( v) * 1023 + 127) / 255)
56
+ #define SOUND_EXPR_DECODE_VOLUME (v ) ((( v) * 255 + 511) / 1023)
57
57
58
- #define SOUND_EXPR_DEFAULT "3""1023""0500""0500""18""000""2500""0000""0000""0128""00""0001""0024""0000000000000000000000000000"
58
+ // #define SOUND_EXPR_DEFAULT "3""1023""0500""0500""18""000""2500""0000""0000""0128""00""0001""0024""0000000000000000000000000000"
59
+ // 310230500050018000250000000000012800000100240000000000000000000000000000
60
+ // 310230500050018000250000000000000000000000000000000000000000000000000000
61
+ // 30=steps
62
+ // 36=fx-param
63
+ // 40=fx-steps
59
64
60
65
#define SOUND_EFFECT_WAVE_SINE (0)
61
66
#define SOUND_EFFECT_WAVE_SAWTOOTH (1)
62
67
#define SOUND_EFFECT_WAVE_TRIANGLE (2)
63
68
#define SOUND_EFFECT_WAVE_SQUARE (3)
64
69
#define SOUND_EFFECT_WAVE_NOISE (4)
65
70
66
- #define SOUND_EFFECT_INTER_LINEAR (1)
67
- #define SOUND_EFFECT_INTER_CURVE (2)
68
- #define SOUND_EFFECT_INTER_LOG (18)
71
+ #define SOUND_EFFECT_SHAPE_LINEAR (1)
72
+ #define SOUND_EFFECT_SHAPE_CURVE (2)
73
+ #define SOUND_EFFECT_SHAPE_LOG (18)
69
74
70
- #define SOUND_EFFECT_FX_NONE (0) // Python "None" object
75
+ #define SOUND_EFFECT_FX_NONE (0)
71
76
#define SOUND_EFFECT_FX_TREMOLO (2)
72
77
#define SOUND_EFFECT_FX_VIBRATO (1)
73
78
#define SOUND_EFFECT_FX_WARBLE (3)
74
79
80
+ #define SOUND_EFFECT_DEFAULT_FREQ_START (500)
81
+ #define SOUND_EFFECT_DEFAULT_FREQ_END (2500)
82
+ #define SOUND_EFFECT_DEFAULT_DURATION (500)
83
+ #define SOUND_EFFECT_DEFAULT_VOL_START (255)
84
+ #define SOUND_EFFECT_DEFAULT_VOL_END (0)
85
+ #define SOUND_EFFECT_DEFAULT_WAVE (SOUND_EFFECT_WAVE_SQUARE)
86
+ #define SOUND_EFFECT_DEFAULT_FX (SOUND_EFFECT_FX_NONE)
87
+ #define SOUND_EFFECT_DEFAULT_SHAPE (SOUND_EFFECT_SHAPE_LOG)
88
+
75
89
typedef struct _microbit_soundeffect_obj_t {
76
90
mp_obj_base_t base ;
77
91
bool is_mutable ;
78
92
char sound_expr [SOUND_EXPR_TOTAL_LENGTH ];
79
93
} microbit_soundeffect_obj_t ;
80
94
95
+ typedef struct _soundeffect_attr_t {
96
+ uint16_t qst ;
97
+ uint8_t offset ;
98
+ uint8_t length ;
99
+ } soundeffect_attr_t ;
100
+
81
101
STATIC const uint16_t wave_to_qstr_table [5 ] = {
82
102
[SOUND_EFFECT_WAVE_SINE ] = MP_QSTR_WAVE_SINE ,
83
103
[SOUND_EFFECT_WAVE_SAWTOOTH ] = MP_QSTR_WAVE_SAWTOOTH ,
@@ -87,12 +107,23 @@ STATIC const uint16_t wave_to_qstr_table[5] = {
87
107
};
88
108
89
109
STATIC const uint16_t fx_to_qstr_table [4 ] = {
90
- [0 ] = MP_QSTR_None ,
110
+ [SOUND_EFFECT_FX_NONE ] = MP_QSTR_FX_NONE ,
91
111
[SOUND_EFFECT_FX_TREMOLO ] = MP_QSTR_FX_TREMOLO ,
92
112
[SOUND_EFFECT_FX_VIBRATO ] = MP_QSTR_FX_VIBRATO ,
93
113
[SOUND_EFFECT_FX_WARBLE ] = MP_QSTR_FX_WARBLE ,
94
114
};
95
115
116
+ STATIC const soundeffect_attr_t soundeffect_attr_table [] = {
117
+ { MP_QSTR_freq_start , SOUND_EXPR_FREQUENCY_START_OFFSET , SOUND_EXPR_FREQUENCY_START_LENGTH },
118
+ { MP_QSTR_freq_end , SOUND_EXPR_FREQUENCY_END_OFFSET , SOUND_EXPR_FREQUENCY_END_LENGTH },
119
+ { MP_QSTR_duration , SOUND_EXPR_DURATION_OFFSET , SOUND_EXPR_DURATION_LENGTH },
120
+ { MP_QSTR_vol_start , SOUND_EXPR_VOLUME_START_OFFSET , SOUND_EXPR_VOLUME_START_LENGTH },
121
+ { MP_QSTR_vol_end , SOUND_EXPR_VOLUME_END_OFFSET , SOUND_EXPR_VOLUME_END_LENGTH },
122
+ { MP_QSTR_wave , SOUND_EXPR_WAVE_OFFSET , SOUND_EXPR_WAVE_LENGTH },
123
+ { MP_QSTR_fx , SOUND_EXPR_FX_CHOICE_OFFSET , SOUND_EXPR_FX_CHOICE_LENGTH },
124
+ { MP_QSTR_shape , SOUND_EXPR_SHAPE_OFFSET , SOUND_EXPR_SHAPE_LENGTH },
125
+ };
126
+
96
127
const char * microbit_soundeffect_get_sound_expr_data (mp_obj_t self_in ) {
97
128
const microbit_soundeffect_obj_t * self = MP_OBJ_TO_PTR (self_in );
98
129
return & self -> sound_expr [0 ];
@@ -131,54 +162,59 @@ STATIC void microbit_soundeffect_print(const mp_print_t *print, mp_obj_t self_in
131
162
unsigned int fx = sound_expr_decode (self , SOUND_EXPR_FX_CHOICE_OFFSET , SOUND_EXPR_FX_CHOICE_LENGTH );
132
163
unsigned int shape = sound_expr_decode (self , SOUND_EXPR_SHAPE_OFFSET , SOUND_EXPR_SHAPE_LENGTH );
133
164
134
- mp_printf (print , "SoundEffect("
135
- "freq_start=%d, "
136
- "freq_end=%d, "
137
- "duration=%d, "
138
- "vol_start=%d, "
139
- "vol_end=%d, "
140
- "wave=%q, "
141
- "fx=%q, " ,
142
- freq_start ,
143
- freq_end ,
144
- duration ,
145
- vol_start ,
146
- vol_end ,
147
- wave_to_qstr_table [wave ],
148
- fx_to_qstr_table [fx ]
149
- );
150
-
151
- // Support shape values that don't have a corresponding constant assigned.
152
- switch (shape ) {
153
- case SOUND_EFFECT_INTER_LINEAR :
154
- mp_printf (print , "interpolation=INTER_LINEAR)" );
155
- break ;
156
- case SOUND_EFFECT_INTER_CURVE :
157
- mp_printf (print , "interpolation=INTER_CURVE)" );
158
- break ;
159
- case SOUND_EFFECT_INTER_LOG :
160
- mp_printf (print , "interpolation=INTER_LOG)" );
161
- break ;
162
- default :
163
- mp_printf (print , "interpolation=%d)" , shape );
164
- break ;
165
+ if (kind == PRINT_STR ) {
166
+ mp_printf (print , "SoundEffect("
167
+ "freq_start=%d, "
168
+ "freq_end=%d, "
169
+ "duration=%d, "
170
+ "vol_start=%d, "
171
+ "vol_end=%d, "
172
+ "wave=%q, "
173
+ "fx=%q, " ,
174
+ freq_start ,
175
+ freq_end ,
176
+ duration ,
177
+ vol_start ,
178
+ vol_end ,
179
+ wave_to_qstr_table [wave ],
180
+ fx_to_qstr_table [fx ]
181
+ );
182
+
183
+ // Support shape values that don't have a corresponding constant assigned.
184
+ switch (shape ) {
185
+ case SOUND_EFFECT_SHAPE_LINEAR :
186
+ mp_printf (print , "shape=SHAPE_LINEAR)" );
187
+ break ;
188
+ case SOUND_EFFECT_SHAPE_CURVE :
189
+ mp_printf (print , "shape=SHAPE_CURVE)" );
190
+ break ;
191
+ case SOUND_EFFECT_SHAPE_LOG :
192
+ mp_printf (print , "shape=SHAPE_LOG)" );
193
+ break ;
194
+ default :
195
+ mp_printf (print , "shape=%d)" , shape );
196
+ break ;
197
+ }
198
+ } else {
199
+ // PRINT_REPR
200
+ mp_printf (print , "SoundEffect(%d, %d, %d, %d, %d, %d, %d, %d)" ,
201
+ freq_start , freq_end , duration , vol_start , vol_end , wave , fx , shape );
165
202
}
166
203
}
167
204
168
205
// Constructor:
169
- // SoundEffect(preset=None, *, freq_start, freq_end, duration, vol_start, vol_end, wave, fx, interpolation )
206
+ // SoundEffect(freq_start, freq_end, duration, vol_start, vol_end, wave, fx, shape )
170
207
STATIC mp_obj_t microbit_soundeffect_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args_in ) {
171
- enum { ARG_preset , ARG_freq_start , ARG_freq_end , ARG_duration , ARG_vol_start , ARG_vol_end , ARG_wave , ARG_fx , ARG_interpolation };
208
+ enum { ARG_freq_start , ARG_freq_end , ARG_duration , ARG_vol_start , ARG_vol_end , ARG_wave , ARG_fx , ARG_shape };
172
209
static const mp_arg_t allowed_args [] = {
173
- { MP_QSTR_preset , MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
174
- { MP_QSTR_freq_start , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
175
- { MP_QSTR_freq_end , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
176
- { MP_QSTR_duration , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
177
- { MP_QSTR_vol_start , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
178
- { MP_QSTR_vol_end , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
179
- { MP_QSTR_wave , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
180
- { MP_QSTR_fx , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
181
- { MP_QSTR_interpolation , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
210
+ { MP_QSTR_freq_start , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_FREQ_START } },
211
+ { MP_QSTR_freq_end , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_FREQ_END } },
212
+ { MP_QSTR_duration , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_DURATION } },
213
+ { MP_QSTR_vol_start , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_VOL_START } },
214
+ { MP_QSTR_vol_end , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_VOL_END } },
215
+ { MP_QSTR_wave , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_WAVE } },
216
+ { MP_QSTR_fx , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_FX } },
217
+ { MP_QSTR_shape , MP_ARG_INT , {.u_int = SOUND_EFFECT_DEFAULT_SHAPE } },
182
218
};
183
219
184
220
// Parse arguments.
@@ -191,63 +227,23 @@ STATIC mp_obj_t microbit_soundeffect_make_new(const mp_obj_type_t *type, size_t
191
227
self -> is_mutable = true;
192
228
193
229
// Initialise the sound expression data with the preset values.
194
- const char * sound_expr_preset = SOUND_EXPR_DEFAULT ;
195
- if (args [ARG_preset ].u_obj != mp_const_none ) {
196
- if (mp_obj_is_type (args [ARG_preset ].u_obj , & microbit_soundeffect_type )) {
197
- sound_expr_preset = microbit_soundeffect_get_sound_expr_data (args [ARG_preset ].u_obj );
198
- } else {
199
- sound_expr_preset = mp_obj_str_get_str (args [ARG_preset ].u_obj );
200
- }
201
- }
202
- memcpy (& self -> sound_expr [0 ], sound_expr_preset , SOUND_EXPR_TOTAL_LENGTH );
230
+ memset (& self -> sound_expr [0 ], '0' , SOUND_EXPR_TOTAL_LENGTH );
231
+ sound_expr_encode (self , SOUND_EXPR_STEPS_OFFSET , SOUND_EXPR_STEPS_LENGTH , 128 );
203
232
204
233
// Modify any given parameters.
205
- if (args [ARG_freq_start ].u_obj != MP_OBJ_NULL ) {
206
- sound_expr_encode (self , SOUND_EXPR_FREQUENCY_START_OFFSET , SOUND_EXPR_FREQUENCY_START_LENGTH , mp_obj_get_int (args [ARG_freq_start ].u_obj ));
207
- }
208
- if (args [ARG_freq_end ].u_obj != MP_OBJ_NULL ) {
209
- sound_expr_encode (self , SOUND_EXPR_FREQUENCY_END_OFFSET , SOUND_EXPR_FREQUENCY_END_LENGTH , mp_obj_get_int (args [ARG_freq_end ].u_obj ));
210
- }
211
- if (args [ARG_duration ].u_obj != MP_OBJ_NULL ) {
212
- sound_expr_encode (self , SOUND_EXPR_DURATION_OFFSET , SOUND_EXPR_DURATION_LENGTH , mp_obj_get_int (args [ARG_duration ].u_obj ));
213
- }
214
- if (args [ARG_vol_start ].u_obj != MP_OBJ_NULL ) {
215
- sound_expr_encode (self , SOUND_EXPR_VOLUME_START_OFFSET , SOUND_EXPR_VOLUME_START_LENGTH , mp_obj_get_int (args [ARG_vol_start ].u_obj ));
216
- }
217
- if (args [ARG_vol_end ].u_obj != MP_OBJ_NULL ) {
218
- sound_expr_encode (self , SOUND_EXPR_VOLUME_END_OFFSET , SOUND_EXPR_VOLUME_END_LENGTH , mp_obj_get_int (args [ARG_vol_end ].u_obj ));
219
- }
220
- if (args [ARG_wave ].u_obj != MP_OBJ_NULL ) {
221
- sound_expr_encode (self , SOUND_EXPR_WAVE_OFFSET , SOUND_EXPR_WAVE_LENGTH , mp_obj_get_int (args [ARG_wave ].u_obj ));
222
- }
223
- if (args [ARG_fx ].u_obj != MP_OBJ_NULL ) {
224
- sound_expr_encode (self , SOUND_EXPR_FX_CHOICE_OFFSET , SOUND_EXPR_FX_CHOICE_LENGTH , args [ARG_fx ].u_obj == mp_const_none ? 0 : mp_obj_get_int (args [ARG_fx ].u_obj ));
225
- }
226
- if (args [ARG_interpolation ].u_obj != MP_OBJ_NULL ) {
227
- sound_expr_encode (self , SOUND_EXPR_SHAPE_OFFSET , SOUND_EXPR_SHAPE_LENGTH , mp_obj_get_int (args [ARG_interpolation ].u_obj ));
228
- }
234
+ sound_expr_encode (self , SOUND_EXPR_FREQUENCY_START_OFFSET , SOUND_EXPR_FREQUENCY_START_LENGTH , args [ARG_freq_start ].u_int );
235
+ sound_expr_encode (self , SOUND_EXPR_FREQUENCY_END_OFFSET , SOUND_EXPR_FREQUENCY_END_LENGTH , args [ARG_freq_end ].u_int );
236
+ sound_expr_encode (self , SOUND_EXPR_DURATION_OFFSET , SOUND_EXPR_DURATION_LENGTH , args [ARG_duration ].u_int );
237
+ sound_expr_encode (self , SOUND_EXPR_VOLUME_START_OFFSET , SOUND_EXPR_VOLUME_START_LENGTH , args [ARG_vol_start ].u_int );
238
+ sound_expr_encode (self , SOUND_EXPR_VOLUME_END_OFFSET , SOUND_EXPR_VOLUME_END_LENGTH , args [ARG_vol_end ].u_int );
239
+ sound_expr_encode (self , SOUND_EXPR_WAVE_OFFSET , SOUND_EXPR_WAVE_LENGTH , args [ARG_wave ].u_int );
240
+ sound_expr_encode (self , SOUND_EXPR_FX_CHOICE_OFFSET , SOUND_EXPR_FX_CHOICE_LENGTH , args [ARG_fx ].u_int );
241
+ sound_expr_encode (self , SOUND_EXPR_SHAPE_OFFSET , SOUND_EXPR_SHAPE_LENGTH , args [ARG_shape ].u_int );
229
242
230
243
// Return new sound effect object
231
244
return MP_OBJ_FROM_PTR (self );
232
245
}
233
246
234
- typedef struct _soundeffect_attr_t {
235
- uint16_t qst ;
236
- uint8_t offset ;
237
- uint8_t length ;
238
- } soundeffect_attr_t ;
239
-
240
- STATIC const soundeffect_attr_t soundeffect_attr_table [] = {
241
- { MP_QSTR_freq_start , SOUND_EXPR_FREQUENCY_START_OFFSET , SOUND_EXPR_FREQUENCY_START_LENGTH },
242
- { MP_QSTR_freq_end , SOUND_EXPR_FREQUENCY_END_OFFSET , SOUND_EXPR_FREQUENCY_END_LENGTH },
243
- { MP_QSTR_duration , SOUND_EXPR_DURATION_OFFSET , SOUND_EXPR_DURATION_LENGTH },
244
- { MP_QSTR_vol_start , SOUND_EXPR_VOLUME_START_OFFSET , SOUND_EXPR_VOLUME_START_LENGTH },
245
- { MP_QSTR_vol_end , SOUND_EXPR_VOLUME_END_OFFSET , SOUND_EXPR_VOLUME_END_LENGTH },
246
- { MP_QSTR_wave , SOUND_EXPR_WAVE_OFFSET , SOUND_EXPR_WAVE_LENGTH },
247
- { MP_QSTR_fx , SOUND_EXPR_FX_CHOICE_OFFSET , SOUND_EXPR_FX_CHOICE_LENGTH },
248
- { MP_QSTR_interpolation , SOUND_EXPR_SHAPE_OFFSET , SOUND_EXPR_SHAPE_LENGTH },
249
- };
250
-
251
247
STATIC void microbit_soundeffect_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
252
248
microbit_soundeffect_obj_t * self = MP_OBJ_TO_PTR (self_in );
253
249
const soundeffect_attr_t * soundeffect_attr = NULL ;
@@ -258,7 +254,8 @@ STATIC void microbit_soundeffect_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
258
254
}
259
255
}
260
256
if (soundeffect_attr == NULL ) {
261
- // Invalid attribute.
257
+ // Invalid attribute, set MP_OBJ_SENTINEL to continue lookup in locals dict.
258
+ dest [1 ] = MP_OBJ_SENTINEL ;
262
259
return ;
263
260
}
264
261
if (dest [0 ] == MP_OBJ_NULL ) {
@@ -282,9 +279,43 @@ STATIC void microbit_soundeffect_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
282
279
}
283
280
}
284
281
285
- // Note: these locals are only accessible as SoundEffect.xxx, because
286
- // microbit_soundeffect_attr handles attribute lookups on instances.
282
+ STATIC mp_obj_t microbit_soundeffect_from_string (mp_obj_t str_in ) {
283
+ microbit_soundeffect_obj_t * self = m_new_obj (microbit_soundeffect_obj_t );
284
+ self -> base .type = & microbit_soundeffect_type ;
285
+ self -> is_mutable = true;
286
+
287
+ // Initialise the sound expression data with the preset values.
288
+ memset (& self -> sound_expr [0 ], '0' , SOUND_EXPR_TOTAL_LENGTH );
289
+ size_t len ;
290
+ const char * str = mp_obj_str_get_data (str_in , & len );
291
+ if (len > SOUND_EXPR_TOTAL_LENGTH ) {
292
+ len = SOUND_EXPR_TOTAL_LENGTH ;
293
+ }
294
+ memcpy (& self -> sound_expr [0 ], str , len );
295
+
296
+ return MP_OBJ_FROM_PTR (self );
297
+ }
298
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (microbit_soundeffect_from_string_obj , microbit_soundeffect_from_string );
299
+ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ (microbit_soundeffect_from_string_staticmethod_obj , MP_ROM_PTR (& microbit_soundeffect_from_string_obj ));
300
+
301
+ STATIC mp_obj_t microbit_soundeffect_copy (mp_obj_t self_in ) {
302
+ microbit_soundeffect_obj_t * self = MP_OBJ_TO_PTR (self_in );
303
+ microbit_soundeffect_obj_t * copy = m_new_obj (microbit_soundeffect_obj_t );
304
+ copy -> base .type = self -> base .type ;
305
+ copy -> is_mutable = true;
306
+ memcpy (& copy -> sound_expr [0 ], & self -> sound_expr [0 ], SOUND_EXPR_TOTAL_LENGTH );
307
+
308
+ return MP_OBJ_FROM_PTR (copy );
309
+ }
310
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (microbit_soundeffect_copy_obj , microbit_soundeffect_copy );
311
+
287
312
STATIC const mp_rom_map_elem_t microbit_soundeffect_locals_dict_table [] = {
313
+ // Static methods.
314
+ { MP_ROM_QSTR (MP_QSTR__from_string ), MP_ROM_PTR (& microbit_soundeffect_from_string_staticmethod_obj ) },
315
+
316
+ // Instance methods.
317
+ { MP_ROM_QSTR (MP_QSTR_copy ), MP_ROM_PTR (& microbit_soundeffect_copy_obj ) },
318
+
288
319
// Class constants.
289
320
#define C (NAME ) { MP_ROM_QSTR (MP_QSTR_ ## NAME ), MP_ROM_INT (SOUND_EFFECT_ ## NAME ) }
290
321
@@ -294,9 +325,9 @@ STATIC const mp_rom_map_elem_t microbit_soundeffect_locals_dict_table[] = {
294
325
C (WAVE_SQUARE ),
295
326
C (WAVE_NOISE ),
296
327
297
- C (INTER_LINEAR ),
298
- C (INTER_CURVE ),
299
- C (INTER_LOG ),
328
+ C (SHAPE_LINEAR ),
329
+ C (SHAPE_CURVE ),
330
+ C (SHAPE_LOG ),
300
331
301
332
C (FX_NONE ),
302
333
C (FX_TREMOLO ),
0 commit comments