2018-03-12 19:09:13 -04:00
/*
* This file is part of the Micro Python project , http : //micropython.org/
*
* The MIT License ( MIT )
*
* Copyright ( c ) 2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
# include <stdint.h>
# include "lib/utils/context_manager_helpers.h"
# include "py/objproperty.h"
# include "py/runtime.h"
2019-07-24 21:57:32 -04:00
# include "shared-bindings/audiocore/WaveFile.h"
2018-03-12 19:09:13 -04:00
# include "shared-bindings/util.h"
2018-07-31 19:53:54 -04:00
# include "supervisor/shared/translate.h"
2018-03-12 19:09:13 -04:00
2019-07-25 22:35:07 -04:00
//| .. currentmodule:: audiocore
2018-03-12 19:09:13 -04:00
//|
//| :class:`WaveFile` -- Load a wave file for audio playback
//| ========================================================
//|
2018-04-13 13:51:01 -04:00
//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
2019-08-03 07:48:55 -04:00
//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
//| an internal buffer.
2018-03-12 19:09:13 -04:00
//|
2019-08-03 07:48:55 -04:00
//| .. class:: WaveFile(file[, buffer])
2018-03-12 19:09:13 -04:00
//|
//| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
2019-05-30 22:01:27 -04:00
//| :param typing.BinaryIO file: Already opened wave file
2019-08-17 05:31:45 -04:00
//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally.
//|
2018-03-12 19:09:13 -04:00
//|
//| Playing a wave file from flash::
//|
//| import board
2019-07-25 22:35:07 -04:00
//| import audiocore
2018-03-12 19:09:13 -04:00
//| import audioio
//| import digitalio
//|
//| # Required for CircuitPlayground Express
//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
//| speaker_enable.switch_to_output(value=True)
//|
//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
2019-07-25 22:35:07 -04:00
//| wav = audiocore.WaveFile(data)
2018-03-12 19:09:13 -04:00
//| a = audioio.AudioOut(board.A0)
//|
//| print("playing")
//| a.play(wav)
//| while a.playing:
//| pass
//| print("stopped")
//|
2019-01-14 20:26:36 -05:00
STATIC mp_obj_t audioio_wavefile_make_new ( const mp_obj_type_t * type , size_t n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
2019-08-03 07:48:55 -04:00
mp_arg_check_num ( n_args , kw_args , 1 , 2 , false ) ;
2018-03-12 19:09:13 -04:00
audioio_wavefile_obj_t * self = m_new_obj ( audioio_wavefile_obj_t ) ;
self - > base . type = & audioio_wavefile_type ;
2019-08-03 07:48:55 -04:00
if ( ! MP_OBJ_IS_TYPE ( args [ 0 ] , & mp_type_fileio ) ) {
2018-07-31 19:53:54 -04:00
mp_raise_TypeError ( translate ( " file must be a file opened in byte mode " ) ) ;
2018-03-12 19:09:13 -04:00
}
2019-08-03 07:48:55 -04:00
uint8_t * buffer = NULL ;
size_t buffer_size = 0 ;
if ( n_args > = 2 ) {
mp_buffer_info_t bufinfo ;
mp_get_buffer_raise ( args [ 1 ] , & bufinfo , MP_BUFFER_WRITE ) ;
buffer = bufinfo . buf ;
buffer_size = bufinfo . len ;
}
common_hal_audioio_wavefile_construct ( self , MP_OBJ_TO_PTR ( args [ 0 ] ) ,
buffer , buffer_size ) ;
2018-03-12 19:09:13 -04:00
return MP_OBJ_FROM_PTR ( self ) ;
}
//| .. method:: deinit()
//|
//| Deinitialises the WaveFile and releases all memory resources for reuse.
//|
STATIC mp_obj_t audioio_wavefile_deinit ( mp_obj_t self_in ) {
audioio_wavefile_obj_t * self = MP_OBJ_TO_PTR ( self_in ) ;
common_hal_audioio_wavefile_deinit ( self ) ;
return mp_const_none ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1 ( audioio_wavefile_deinit_obj , audioio_wavefile_deinit ) ;
2019-06-12 04:00:59 -04:00
STATIC void check_for_deinit ( audioio_wavefile_obj_t * self ) {
if ( common_hal_audioio_wavefile_deinited ( self ) ) {
raise_deinited_error ( ) ;
}
}
2018-03-12 19:09:13 -04:00
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
//|
// Provided by context manager helper.
//| .. method:: __exit__()
//|
//| Automatically deinitializes the hardware when exiting a context. See
//| :ref:`lifetime-and-contextmanagers` for more info.
//|
STATIC mp_obj_t audioio_wavefile_obj___exit__ ( size_t n_args , const mp_obj_t * args ) {
( void ) n_args ;
common_hal_audioio_wavefile_deinit ( args [ 0 ] ) ;
return mp_const_none ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN ( audioio_wavefile___exit___obj , 4 , 4 , audioio_wavefile_obj___exit__ ) ;
//| .. attribute:: sample_rate
//|
//| 32 bit value that dictates how quickly samples are loaded into the DAC
//| in Hertz (cycles per second). When the sample is looped, this can change
//| the pitch output without changing the underlying sample.
//|
STATIC mp_obj_t audioio_wavefile_obj_get_sample_rate ( mp_obj_t self_in ) {
audioio_wavefile_obj_t * self = MP_OBJ_TO_PTR ( self_in ) ;
2019-06-12 04:00:59 -04:00
check_for_deinit ( self ) ;
2018-03-12 19:09:13 -04:00
return MP_OBJ_NEW_SMALL_INT ( common_hal_audioio_wavefile_get_sample_rate ( self ) ) ;
}
MP_DEFINE_CONST_FUN_OBJ_1 ( audioio_wavefile_get_sample_rate_obj , audioio_wavefile_obj_get_sample_rate ) ;
STATIC mp_obj_t audioio_wavefile_obj_set_sample_rate ( mp_obj_t self_in , mp_obj_t sample_rate ) {
audioio_wavefile_obj_t * self = MP_OBJ_TO_PTR ( self_in ) ;
2019-06-12 04:00:59 -04:00
check_for_deinit ( self ) ;
2018-03-12 19:09:13 -04:00
common_hal_audioio_wavefile_set_sample_rate ( self , mp_obj_get_int ( sample_rate ) ) ;
return mp_const_none ;
}
MP_DEFINE_CONST_FUN_OBJ_2 ( audioio_wavefile_set_sample_rate_obj , audioio_wavefile_obj_set_sample_rate ) ;
const mp_obj_property_t audioio_wavefile_sample_rate_obj = {
. base . type = & mp_type_property ,
. proxy = { ( mp_obj_t ) & audioio_wavefile_get_sample_rate_obj ,
( mp_obj_t ) & audioio_wavefile_set_sample_rate_obj ,
( mp_obj_t ) & mp_const_none_obj } ,
} ;
2018-10-31 21:08:10 -04:00
//| .. attribute:: bits_per_sample
//|
//| Bits per sample. (read only)
//|
STATIC mp_obj_t audioio_wavefile_obj_get_bits_per_sample ( mp_obj_t self_in ) {
audioio_wavefile_obj_t * self = MP_OBJ_TO_PTR ( self_in ) ;
2019-06-12 04:00:59 -04:00
check_for_deinit ( self ) ;
2018-10-31 21:08:10 -04:00
return MP_OBJ_NEW_SMALL_INT ( common_hal_audioio_wavefile_get_bits_per_sample ( self ) ) ;
}
MP_DEFINE_CONST_FUN_OBJ_1 ( audioio_wavefile_get_bits_per_sample_obj , audioio_wavefile_obj_get_bits_per_sample ) ;
const mp_obj_property_t audioio_wavefile_bits_per_sample_obj = {
. base . type = & mp_type_property ,
. proxy = { ( mp_obj_t ) & audioio_wavefile_get_bits_per_sample_obj ,
( mp_obj_t ) & mp_const_none_obj ,
( mp_obj_t ) & mp_const_none_obj } ,
} ;
2018-11-05 17:49:24 -05:00
//| .. attribute:: channel_count
2018-10-31 21:08:10 -04:00
//|
//| Number of audio channels. (read only)
//|
STATIC mp_obj_t audioio_wavefile_obj_get_channel_count ( mp_obj_t self_in ) {
audioio_wavefile_obj_t * self = MP_OBJ_TO_PTR ( self_in ) ;
2019-06-12 04:00:59 -04:00
check_for_deinit ( self ) ;
2018-10-31 21:08:10 -04:00
return MP_OBJ_NEW_SMALL_INT ( common_hal_audioio_wavefile_get_channel_count ( self ) ) ;
}
MP_DEFINE_CONST_FUN_OBJ_1 ( audioio_wavefile_get_channel_count_obj , audioio_wavefile_obj_get_channel_count ) ;
const mp_obj_property_t audioio_wavefile_channel_count_obj = {
. base . type = & mp_type_property ,
. proxy = { ( mp_obj_t ) & audioio_wavefile_get_channel_count_obj ,
( mp_obj_t ) & mp_const_none_obj ,
( mp_obj_t ) & mp_const_none_obj } ,
} ;
2018-03-12 19:09:13 -04:00
STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table [ ] = {
// Methods
{ MP_ROM_QSTR ( MP_QSTR_deinit ) , MP_ROM_PTR ( & audioio_wavefile_deinit_obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR___enter__ ) , MP_ROM_PTR ( & default___enter___obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR___exit__ ) , MP_ROM_PTR ( & audioio_wavefile___exit___obj ) } ,
// Properties
{ MP_ROM_QSTR ( MP_QSTR_sample_rate ) , MP_ROM_PTR ( & audioio_wavefile_sample_rate_obj ) } ,
2018-10-31 21:08:10 -04:00
{ MP_ROM_QSTR ( MP_QSTR_bits_per_sample ) , MP_ROM_PTR ( & audioio_wavefile_bits_per_sample_obj ) } ,
2018-11-05 11:05:43 -05:00
{ MP_ROM_QSTR ( MP_QSTR_channel_count ) , MP_ROM_PTR ( & audioio_wavefile_channel_count_obj ) } ,
2018-03-12 19:09:13 -04:00
} ;
STATIC MP_DEFINE_CONST_DICT ( audioio_wavefile_locals_dict , audioio_wavefile_locals_dict_table ) ;
const mp_obj_type_t audioio_wavefile_type = {
{ & mp_type_type } ,
. name = MP_QSTR_WaveFile ,
. make_new = audioio_wavefile_make_new ,
. locals_dict = ( mp_obj_dict_t * ) & audioio_wavefile_locals_dict ,
} ;