diff --git a/README.md b/README.md index 0d5639d..0dd8228 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,42 @@ # pedales -## Intro +Algunos pedales para Figueroa Lab. -Hacer pedales de guitarra, bajo y otros instrumentos, es sencillo. +- [Imitator](https://github.com/fede2cr/pedales/tree/master/imitator) -Solo necesita aprender a soldar y a ensamblar componentes teniendo un poco de cuidado. Poco a poco iremos experimentando en cambiar compomentes en los diseños y observando la función de los diferentes transistores, capacitores y resistencias que componen estos sencillos circuitos. +Utiliza alucinación de inteligencia artificial para separar cualquier canción en voz, percusión, bajo y otros (guitarras, teclados, vientos, etc) y luego con los controles del pedal podemos realizar una mezcla en vivo, o eliminar uno o varios instrumentos. -Todos los diseños que usaremos con ejemplos clásicos de pedales, disponibles en múltiples foros en Internet y en libros especializados. +Esto le permite ser un pedal de "super-karaoke", ya que podemos eliminar la voz para usarlo como un karaoke tradicional, así como también eliminar una guitarra, o la batería o el bajo; para practicar encima de tu canción preferida -Lista de pedales: +[![Imitator demo](https://img.youtube.com/vi/_IGj-wyZRRc/default.jpg)](https://youtu.be/_IGj-wyZRRc) -- [Amplificador LM386](https://github.com/fede2cr/pedales/tree/master/ampli-lm386) +¿Como funciona? Con una librería de inteligencia artificial llamada demucs, el pedal imagina o alucina como debería sonar el instrumento original antes de ser mezclado en el estudio. -![Prototipo de Amplificador LM386](https://github.com/fede2cr/pedales/blob/master/ampli-lm386/img/prototipo%20ampli-lm386.jpg) +Se recomienda el pedal para investigadores de AI, pero también para cualquiera que quiera mostrar al mundo como toca un instrumento como si fuera parte de su grupo preferido. -- [Bazz Fuss](https://github.com/fede2cr/pedales/tree/master/bazz%20fuss) +- [Guatusa](https://github.com/fede2cr/pedales/tree/master/guatusa) + +Es un pedal que funciona como teclado bluetooth, por lo que lo puedes conectar con computadoras, tabletas, teléfonos y otros dispositivos. + +Con esto puedes controlar de manera sencilla aplicaciones como youtube, tu estación de audio favorita, pasar la página de una partitura en la tableta, y muchas otras funciones. Puedes agregar tus propias combinaciones de teclas de manera muy sencilla, así como enlazar varios pedales para pasar la página de la partitura para todos los músicos en escenario. + +![Guatusa](/doc/img/guatusa.jpg) + +- [Chicharra](https://github.com/fede2cr/pedales/tree/master/chicharra) + +Un trémolo versatil, ya que puedes usar los modos predefinidos, pero también puedes agregar diferentes formas de modular tu trémolo, y hacerlo que suene como una chicharra si así lo deseas. + +![Chicharra](/doc/img/chicharra-top.jpg) + +## Jícaras + +Los pedales no utilizan cajas de metal como el resto de pedales, sino que pensando en revitalizar técnicas artesanales indígenas y buscando maneras creativas para tener un menor impacto sobre la huella de carbono, estos pedales son construídos de manera artesanal utilizando jícaras como la base estructural de los pedales. + +Todos los pedales van a incluír esta historieta que explica la relevancia de la Jícara en el libro sagrado *Popol Vuh*, y estamos en progreso de recolectar otras historias indígenas de culturas de Costa Rica para difundir esta importante pero olvidada especie. + +![Ixquic y las jícaras - Extrato del Popol Vuh](/doc/Ixquic_y_las_jícaras.pdf) + +## Software libre y hardware libre + +Todos los pedales diseñados son software libre y hardware libre, lo que quiere decir que tanto la manera como han sido programados, así como los componentes y la forma en como se conectan, es información que acompaña a estos pedales. De forma que puedan ser reparados, mejorados y copiados; solo se solicita que los cambios también sean publicados de manera que toda la comunidad de pedales pueda avanzar al mismo tiempo. -![Prototipo de Bazz Fuss](https://github.com/fede2cr/pedales/blob/master/bazz%20fuss/img/prototipo%20bazz%20fuss.jpg) diff --git a/ampli-lm386/img/prototipo ampli-lm386.jpg b/ampli-lm386/img/prototipo ampli-lm386.jpg deleted file mode 100644 index 7cc103a..0000000 Binary files a/ampli-lm386/img/prototipo ampli-lm386.jpg and /dev/null differ diff --git a/bazz fuss/img/prototipo bazz fuss.jpg b/bazz fuss/img/prototipo bazz fuss.jpg deleted file mode 100644 index 7d08706..0000000 Binary files a/bazz fuss/img/prototipo bazz fuss.jpg and /dev/null differ diff --git a/chicharra/pedal/code.py b/chicharra/pedal/code.py new file mode 100644 index 0000000..6260619 --- /dev/null +++ b/chicharra/pedal/code.py @@ -0,0 +1,85 @@ +import time +import board +import neopixel +import adafruit_ds3502 +from adafruit_seesaw import neopixel, seesaw, rotaryio, digitalio +from adafruit_debouncer import Button + +''' +Helper function arduino-like map(), to map the volume (1-127) to LED +intensity (0-255). The first argument is the value to convert, and it +returns the converted value. + +Example: +y = _map_vol_to_color(25) +''' +def _map_vol_to_color(volume): + return int((volume - 0) * (255 - 0) / (127 - 0) + 0) + +def square(pixel, speed): + TIME_CONST = 10 + pixel.fill((255, 0, 0)) + time.sleep(speed*TIME_CONST) + pixel.fill((0, 0, 0)) + time.sleep(speed*TIME_CONST) + +def saw(pixel, speed): + for volumen in range(0, 255, 5): + pixel.fill((volumen, 0, 0)) + time.sleep(speed) + +def saw_reverse(pixel, speed): + for volumen in range(255, 0, -5): + pixel.fill((volumen, 0, 0)) + time.sleep(speed) + +def triangle(pixel, speed): + saw(pixel, speed) + saw_reverse(pixel, speed) + +i2c = board.STEMMA_I2C() +ds3502 = adafruit_ds3502.DS3502(i2c) +ds3502.wiper = 127 + +mode_ss = seesaw.Seesaw(i2c, addr=0x36) +speed_ss = seesaw.Seesaw(i2c, addr=0x37) +depth_ss = seesaw.Seesaw(i2c, addr=0x38) + +mode_ss.pin_mode(24, mode_ss.INPUT_PULLUP) +mode_button = digitalio.DigitalIO(mode_ss, 24) +mode_pixel = neopixel.NeoPixel(mode_ss, 6, 1) +mode_encoder = rotaryio.IncrementalEncoder(mode_ss) + +speed_ss.pin_mode(24, speed_ss.INPUT_PULLUP) +speed_button = digitalio.DigitalIO(speed_ss, 24) +speed_pixel = neopixel.NeoPixel(speed_ss, 6, 1) +speed_encoder = rotaryio.IncrementalEncoder(speed_ss) + +depth_ss.pin_mode(24, depth_ss.INPUT_PULLUP) +depth_button = digitalio.DigitalIO(depth_ss, 24) +depth_pixel = neopixel.NeoPixel(depth_ss, 6, 1) +depth_encoder = rotaryio.IncrementalEncoder(depth_ss) + +mode_pixel.fill((255,0,0)) +speed_pixel.fill((0,255,0)) +depth_pixel.fill((0,0,255)) + +speed = 0.05 + +while True: + square(mode_pixel, speed) + square(mode_pixel, speed) + square(mode_pixel, speed) + saw(mode_pixel, speed) + saw_reverse(mode_pixel, speed) + triangle(mode_pixel, speed) + mode_pixel.fill((255,0,0)) + ds3502.wiper = 127 + print("Wiper set to %d" % ds3502.wiper) + time.sleep(3) + ds3502.wiper = 0 + print("Wiper set to %d" % ds3502.wiper) + time.sleep(3) + ds3502.wiper = 63 + print("Wiper set to %d" % ds3502.wiper) + time.sleep(3) diff --git "a/doc/Ixquic_y_las_j\303\255caras.pdf" "b/doc/Ixquic_y_las_j\303\255caras.pdf" new file mode 100644 index 0000000..261c218 Binary files /dev/null and "b/doc/Ixquic_y_las_j\303\255caras.pdf" differ diff --git a/doc/img/chicharra-side.jpg b/doc/img/chicharra-side.jpg new file mode 100644 index 0000000..667bdee Binary files /dev/null and b/doc/img/chicharra-side.jpg differ diff --git a/doc/img/chicharra-top.jpg b/doc/img/chicharra-top.jpg new file mode 100644 index 0000000..1215541 Binary files /dev/null and b/doc/img/chicharra-top.jpg differ diff --git a/doc/img/guatusa.jpg b/doc/img/guatusa.jpg new file mode 100644 index 0000000..d2e3d1e Binary files /dev/null and b/doc/img/guatusa.jpg differ diff --git a/guatusa/apps.py b/guatusa/apps.py new file mode 100755 index 0000000..f1b0a47 --- /dev/null +++ b/guatusa/apps.py @@ -0,0 +1,23 @@ +''' +Add your application codes here. + +You add an app by creating a variable name with the name +of the app, inside in [] you define a color in rgb in format +similar to (255, 0, 0), then if the mode has to send text or +a particular keycode, with the value in a tuple. In the format: + +app_name = [ (0, 255, 255), "L", Keycode.ENTER ] + +The ```modes``` variable has the enabled modes. + +Keycodes are documented [here](https://docs.circuitpython.org/projects/hid/en/latest/_modules/adafruit_hid/keycode.html): +''' + +from adafruit_hid.keycode import Keycode + +youtube = [ (255, 0, 0), "<", ">" ] +tableta = [ (0, 255, 0), Keycode.PAGE_UP, Keycode.PAGE_DOWN] +audacity = [ (0, 255, 255), "R", Keycode.SPACE ] +mpv = [ (255, 255, 0), Keycode.LEFT_ARROW, "p" ] +modes = [ youtube, tableta, audacity, mpv ] + diff --git a/guatusa/code.py b/guatusa/code.py new file mode 100755 index 0000000..b7ede37 --- /dev/null +++ b/guatusa/code.py @@ -0,0 +1,106 @@ +""" +""" +import time +import board +from digitalio import DigitalInOut, Direction, Pull +from adafruit_seesaw import seesaw, neopixel, rotaryio, digitalio +from analogio import AnalogIn +from adafruit_debouncer import Button + +import adafruit_ble +from adafruit_ble.advertising import Advertisement +from adafruit_ble.advertising.standard import ProvideServicesAdvertisement +from adafruit_ble.services.standard.hid import HIDService +from adafruit_ble.services.standard.device_info import DeviceInfoService +from adafruit_hid.keyboard import Keyboard +from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS +from adafruit_hid.keycode import Keycode + +import apps + +vbat_voltage = AnalogIn(board.VOLTAGE_MONITOR) +seesaw = seesaw.Seesaw(board.I2C(), 0x36) + +encoder = rotaryio.IncrementalEncoder(seesaw) +seesaw.pin_mode(24, seesaw.INPUT_PULLUP) + +pixel = neopixel.NeoPixel(seesaw, 6, 1) + +pedal_button_left = DigitalInOut(board.D6) +pedal_button_left.direction = Direction.INPUT +pedal_button_left.pull = Pull.UP +pedal_pressed_left = Button(pedal_button_left, long_duration_ms=500, interval=0.01) + +pedal_button_right = DigitalInOut(board.D5) +pedal_button_right.direction = Direction.INPUT +pedal_button_right.pull = Pull.UP +pedal_pressed_right = Button(pedal_button_right, long_duration_ms=500, interval=0.01) + +last_position = -1 + +hid = HIDService() + +device_info = DeviceInfoService(software_revision=adafruit_ble.__version__, + manufacturer="Adafruit Industries") +advertisement = ProvideServicesAdvertisement(hid) +advertisement.appearance = 961 +scan_response = Advertisement() +scan_response.complete_name = "CircuitPython HID" + +ble = adafruit_ble.BLERadio() + +ble.name = "guatusa" + +if not ble.connected: + pixel.fill((255,255,255)) + print("advertising") + ble.start_advertising(advertisement, scan_response) +else: + print("already connected") + print(ble.connections) + +def pedal_button(botones): + ''' + Converts the buttons to keyboard events + ''' + pedal_pressed_left.update() + pedal_pressed_right.update() + if pedal_pressed_left.short_count: + print(botones) + print(type(botones[1])) + if isinstance(botones[1], str): + kl.write(botones[1]) + else: + k.send(botones[1]) + + if pedal_pressed_right.short_count: + print(botones) + if isinstance(botones[2], str): + kl.write(botones[2]) + else: + k.send(botones[2]) + +def get_voltage(pin): + return (pin.value * 3.6) / 65536 * 2 + +k = Keyboard(hid.devices) +kl = KeyboardLayoutUS(k) +while True: + while not ble.connected: + pass + print("Start typing:") + + while ble.connected: + # negate the position to make clockwise rotation positive + position = -encoder.position + + #position = 0 + if position != last_position: + print(position) + print(apps.modes[position%len(apps.modes)]) + pixel.fill(apps.modes[position%len(apps.modes)][0]) + pedal_button(apps.modes[position%len(apps.modes)]) + + last_position = position + + ble.start_advertising(advertisement) diff --git a/imitator/README.md b/imitator/README.md index 47cb144..fd323ea 100644 --- a/imitator/README.md +++ b/imitator/README.md @@ -14,6 +14,12 @@ It has one button to control with short presses (play/pause), four rotary encode With this pedal you can plug it separately to a PA or speakers two have better audio quality, or directly to your amp with a pedal like [JHS Summing Amp](https://www.jhspedals.info/summing-amp) and play it straight to your amp. You can also use something like [TC Electronic Wiretap](https://www.tcelectronic.com/product.html?modelCode=P0CM1) to record only your guitar part if used after your pedal chain, or to record the complete song if used after the imitator pedal. +## Workflow + +The pedal will start with a "fire" screensaver to indicate that it is ready to be used. While in this mode, you can press the pedal button to start playing, or the most left or right buttons to switch to a previous or next song. + +Once it is in play mode, you can press the pedal button for pause/unpause, press the rotary encoder buttons to mute a channel, or turn their knobs to change the channel volume. Once it finish playing a song, it will get back to standby mode with the screensaver. + ## Limitations ### Guitar and other instruments @@ -21,7 +27,3 @@ With this pedal you can plug it separately to a PA or speakers two have better a The un-mix technology is provided by the free software from Facebook called [demucs](https://github.com/facebookresearch/demucs) which currently splits the audio in four channels: voice, bass, drums and **others**. This means that the guitar audio will be split combined with other instruments such as keyboards, winds, brass and others, which means that some songs that have heavy use of this sounds, will have it removed if you mute the "guitar" (called "others") channel. There is experimental training that can be used to teach the demucs software to remove only the guitar, but it does not work as good as it does for bass, drums or vocals. - -### Rotary encoders - -Also, the rotary encoders can only read when they change, not where they are. So it is recommended that before starting a playing session, to turn the knobs to "12" to indicate 100% volume. diff --git a/imitator/pedal/imitator_pedal.py b/imitator/pedal/imitator_pedal.py new file mode 100644 index 0000000..2fd4775 --- /dev/null +++ b/imitator/pedal/imitator_pedal.py @@ -0,0 +1,328 @@ +''' +Code that runs on the pedal "imitator". + +It receives 4 channels of demixed audio and plays them. + +When no song is playing the controls are the button to start playing, +the most left and right rotary encoder buttons to select a song. + +When playing, therotary encoders you can set the volume of each channel, +or mute it. The button is for pause/unpause and a long press for rewind. + +Use time with care: no pauses are good. +''' + +import board +import digitalio as pigpio +import os +import time +from adafruit_seesaw import neopixel, seesaw, rotaryio, digitalio +from adafruit_debouncer import Button +from pygame import mixer + +''' +Helper function arduino-like map(), to map the volume (1-100) to LED +intensity (0-255). The first argument is the value to convert, and it +returns the converted value. + +Example: +y = _map(25) +''' +def _map_vol_to_color(volume): + return int((volume - 0) * (255 - 0) / (100 - 0) + 0) + +''' +Function that displays a screensaver after the pedal has booted and it's ready to be played. +If you press the pedal button it starts playing the current song. +If you press the most left or right rotary encoder buttons, it will switch tracks to the previous or next song, and show an animation. +''' +def standby(): + drums_button_held = bass_button_held = vocals_button_held = other_button_held = False + media_dir = '/home/imitator/imitator-media/' + tracks_available = [ { # TODO: hardcode + 'drums': media_dir + 'strut/drums.wav', + 'bass': media_dir + 'strut/bass.wav', + 'vocals': media_dir + 'strut/vocals.wav', + 'other': media_dir + 'strut/other.wav', + }, + { + 'drums': media_dir + 'revolution/drums.wav', + 'bass': media_dir + 'revolution/bass.wav', + 'vocals': media_dir + 'revolution/vocals.wav', + 'other': media_dir + 'revolution/other.wav', + } ] + selected_track = 0 + drums_pixel.fill((0,0,0)) + bass_pixel.fill((0,0,0)) + vocals_pixel.fill((0,0,0)) + other_pixel.fill((0,0,0)) + drums_button_held = vocals_button_held = bass_button_held = other_button_held = False + while True: + pedal_pressed.update() + screensaver() + # next song + if not other_button.value and not other_button_held: + selected_track = ((selected_track+1) % len(tracks_available)) + track_animation('left') + if other_button.value and other_button_held: + other_button_held = False + # prev song + if not drums_button.value and not drums_button_held: + selected_track = ((selected_track-1) % len(tracks_available)) + track_animation('right') + if drums_button.value and drums_button_held: + drums_button_held = False + if not vocals_button.value and not vocals_button_held and not bass_button.value and not bass_button_held: + print("shutdown") + os.system("sudo poweroff") + if pedal_pressed.short_count: + playing(tracks_available[selected_track]) + + +''' +Function to play the audio. +It sets a color for each channel LED. +Uses the audio files to create the mixer channels, and starts playing. +It handles pause/unpause, mute/unmute, rewind, and channel volume. +It finishes working after playing, and does not return values. +''' +def playing(tracks): + drums_pixel.fill((255,0,0)) + bass_pixel.fill((0,255,0)) + vocals_pixel.fill((0,0,255)) + other_pixel.fill((255, 255, 0)) + drums_button_held = bass_button_held = vocals_button_held = other_button_held = False + drums_last_position = bass_last_position = vocals_last_position = other_last_position = 0 + drums_mutted = bass_mutted = other_mutted = vocals_mutted = False + drums_volume = bass_volume = vocals_volume = other_volume = 100 + paused = False + + mixer.init() + drums_track = mixer.Sound(file=tracks['drums']) + bass_track = mixer.Sound(file=tracks['bass']) + vocals_track = mixer.Sound(file=tracks['vocals']) + other_track = mixer.Sound(file=tracks['other']) + + bass_track.play() + drums_track.play() + vocals_track.play() + other_track.play() + + while mixer.get_busy(): + pedal_pressed.update() + if pedal_pressed.short_count: + if not paused: + mixer.pause() + paused = True + print("Pause") + else: + mixer.unpause() + paused = False + print("Unpause") + if pedal_pressed.long_press: # rewind + print("long press, rewind") + mixer.stop() + bass_track.play() + drums_track.play() + vocals_track.play() + other_track.play() + + #0: Drums + drums_volume, drums_last_position = channel_volume('drums', drums_volume, + drums_track, drums_last_position, drums_encoder, drums_pixel) + + if not drums_button.value and not drums_button_held: + drums_mutted = channel_mute(drums_track, 'drums', + drums_volume, drums_pixel, drums_mutted) + drums_button_held = True + + if drums_button.value and drums_button_held: + drums_button_held = False + + #1: Bass + bass_volume, bass_last_position = channel_volume('bass', bass_volume, + bass_track, bass_last_position, bass_encoder, bass_pixel) + if not bass_button.value and not bass_button_held: + bass_mutted = channel_mute(bass_track, 'bass', + bass_volume, bass_pixel, bass_mutted) + bass_button_held = True + + if bass_button.value and bass_button_held: + bass_button_held = False + + #2: Vocals + vocals_volume, vocals_last_position = channel_volume('vocals', vocals_volume, + vocals_track, vocals_last_position, vocals_encoder, vocals_pixel) + if not vocals_button.value and not vocals_button_held: + vocals_mutted = channel_mute(vocals_track, 'vocals', + vocals_volume, vocals_pixel, vocals_mutted) + vocals_button_held = True + + if vocals_button.value and vocals_button_held: + vocals_button_held = False + + #3: Other (+guitar) + other_volume, other_last_position = channel_volume('other', other_volume, + other_track, other_last_position, other_encoder, other_pixel) + + if not other_button.value and not other_button_held: + other_mutted = channel_mute(other_track, 'other', + other_volume, other_pixel, other_mutted) + other_button_held = True + + if other_button.value and other_button_held: + other_button_held = False + mixer.quit() + drums_pixel.fill((0,0,0)) + bass_pixel.fill((0,0,0)) + vocals_pixel.fill((0,0,0)) + other_pixel.fill((0,0,0)) + +''' +Comment +''' +def screensaver(): + drums_pixel.fill((50,50,50)) + bass_pixel.fill((50,50,50)) + vocals_pixel.fill((50,50,50)) + other_pixel.fill((50,50,50)) + +''' +Comment +''' +def track_animation(direction): + if direction == 'left': + drums_pixel.fill((255,255,255)) + time.sleep(0.05) + drums_pixel.fill((0,0,0)) + time.sleep(0.05) + bass_pixel.fill((255,255,255)) + time.sleep(0.05) + bass_pixel.fill((0,0,0)) + time.sleep(0.05) + vocals_pixel.fill((255,255,255)) + time.sleep(0.05) + vocals_pixel.fill((0,0,0)) + time.sleep(0.05) + other_pixel.fill((255,255,255)) + time.sleep(0.05) + other_pixel.fill((0,0,0)) + else: + other_pixel.fill((255,255,255)) + time.sleep(0.05) + other_pixel.fill((0,0,0)) + time.sleep(0.05) + vocals_pixel.fill((255,255,255)) + time.sleep(0.05) + vocals_pixel.fill((0,0,0)) + bass_pixel.fill((255,255,255)) + time.sleep(0.05) + bass_pixel.fill((0,0,0)) + time.sleep(0.05) + drums_pixel.fill((255,255,255)) + time.sleep(0.05) + drums_pixel.fill((0,0,0)) + time.sleep(0.05) + + +''' +It receives a channel name, and paints the pixel depending +of the channel name +''' +def paint_pixel(channel_name, channel_volume, pixel): + if channel_name == 'drums': + pixel.fill((_map_vol_to_color(channel_volume),0,0)) + if channel_name == 'bass': + pixel.fill((0,_map_vol_to_color(channel_volume),0)) + if channel_name == 'vocals': + pixel.fill((0, 0, _map_vol_to_color(channel_volume))) + if channel_name == 'other': + pixel.fill((_map_vol_to_color(channel_volume),_map_vol_to_color(channel_volume),0)) + +''' +Comment +''' +def channel_mute(channel, channel_name, channel_volume, pixel, mutted): + if not mutted: + print(channel_name + " mutted") + channel.set_volume(0) + mutted = True + pixel.fill((0,0,0)) + else: + print(channel_name + " un-mutted") + channel.set_volume(channel_volume) + mutted = False + if mutted: + pixel.fill((0,0,0)) + else: + paint_pixel(channel_name, channel_volume, pixel) + + return mutted + +''' +Comment +''' +def channel_volume(channel_name, channel_volume, channel_track, channel_last_position, channel_encoder, pixel): + channel_position = -channel_encoder.position + + if channel_position != channel_last_position and abs(channel_position) < 1000: + if channel_position > channel_last_position: + if channel_volume < 100: + channel_volume += 5 + else: + print("limite 100") + for _ in range(3): + pixel.fill((0,0,0)) + time.sleep(0.05) + paint_pixel(channel_name, channel_volume, pixel) + time.sleep(0.05) + else: + if channel_volume > 0: + channel_volume -= 5 + else: + print("limite 0") + for _ in range(3): + paint_pixel(channel_name, 100, pixel) + time.sleep(0.05) + pixel.fill((0,0,0)) + time.sleep(0.05) + channel_track.set_volume(channel_volume/100) + channel_last_position = channel_position + paint_pixel(channel_name, channel_volume, pixel) + return channel_volume, channel_last_position + +i2c = board.I2C() + +drums_ss = seesaw.Seesaw(i2c, addr=0x36) +bass_ss = seesaw.Seesaw(i2c, addr=0x37) +vocals_ss = seesaw.Seesaw(i2c, addr=0x38) +other_ss = seesaw.Seesaw(i2c, addr=0x39) + +drums_ss.pin_mode(24, drums_ss.INPUT_PULLUP) +drums_button = digitalio.DigitalIO(drums_ss, 24) +drums_pixel = neopixel.NeoPixel(drums_ss, 6, 1) +drums_encoder = rotaryio.IncrementalEncoder(drums_ss) + +bass_ss.pin_mode(24, bass_ss.INPUT_PULLUP) +bass_button = digitalio.DigitalIO(bass_ss, 24) +bass_pixel = neopixel.NeoPixel(bass_ss, 6, 1) +bass_encoder = rotaryio.IncrementalEncoder(bass_ss) + +vocals_ss.pin_mode(24, vocals_ss.INPUT_PULLUP) +vocals_button = digitalio.DigitalIO(vocals_ss, 24) +vocals_pixel = neopixel.NeoPixel(vocals_ss, 6, 1) +vocals_encoder = rotaryio.IncrementalEncoder(vocals_ss) + +other_ss.pin_mode(24, other_ss.INPUT_PULLUP) +other_button = digitalio.DigitalIO(other_ss, 24) +other_pixel = neopixel.NeoPixel(other_ss, 6, 1) +other_encoder = rotaryio.IncrementalEncoder(other_ss) + +pedal_button = pigpio.DigitalInOut(board.D21) +pedal_button.direction = pigpio.Direction.INPUT +pedal_button.pull = pigpio.Pull.UP +pedal_pressed = Button(pedal_button, long_duration_ms=500, interval=0.01) + + + +standby() diff --git a/imitator/test_code/pygame_mixer.py b/imitator/test_code/pygame_mixer.py deleted file mode 100644 index 82fb363..0000000 --- a/imitator/test_code/pygame_mixer.py +++ /dev/null @@ -1,45 +0,0 @@ -''' -Test code for the pygame mixer library. - -You need to have present the files 'bass.wav', 'drums.wav', -'other.wav' and 'vocals.wav' inside test_data/ - -Note: using the music class can only handle one at a time. -''' - -import time -from pygame import mixer - -mixer.init() - -print(mixer.get_num_channels()) -print(mixer.get_busy()) - -bass = mixer.Sound(file='test_data/bass.wav') -drums = mixer.Sound(file='test_data/drums.wav') -vocals = mixer.Sound(file='test_data/vocals.wav') -other = mixer.Sound(file='test_data/other.wav') -bass.play() -drums.play() -vocals.play() -other.play() -bass.set_volume(0.7) -drums.set_volume(0.7) - -time.sleep(5) -mixer.pause() -time.sleep(2) -mixer.unpause() - -time.sleep(20) -other_volume_before_mute=other.get_volume() -other.set_volume(0) -time.sleep(10) -other.set_volume(other_volume_before_mute) -while mixer.get_busy(): - print('.', end='') - time.sleep(1) - -print(mixer.get_num_channels()) - -mixer.quit() diff --git a/imitator/test_code/pygame_rotary.py b/imitator/test_code/pygame_rotary.py index 54d3252..4bdcb2d 100644 --- a/imitator/test_code/pygame_rotary.py +++ b/imitator/test_code/pygame_rotary.py @@ -7,11 +7,11 @@ Note: using the music class can only handle one at a time. ''' -import time import board -from pygame import mixer -from rainbowio import colorwheel +import digitalio as pigpio from adafruit_seesaw import neopixel, seesaw, rotaryio, digitalio +from adafruit_debouncer import Button +from pygame import mixer mixer.init() i2c = board.I2C() @@ -43,7 +43,6 @@ bass_mutted = False bass_volume = 100 - vocals_ss.pin_mode(24, vocals_ss.INPUT_PULLUP) vocals_button = digitalio.DigitalIO(vocals_ss, 24) vocals_button_held = False @@ -66,6 +65,13 @@ other_mutted = False other_volume = 100 +pedal_button = pigpio.DigitalInOut(board.D21) +pedal_button.direction = pigpio.Direction.INPUT +pedal_button.pull = pigpio.Pull.UP +#pedal_pressed = Debouncer(pedal_button, long_duration_ms=500, interval=0.05) +pedal_pressed = Button(pedal_button, long_duration_ms=500, interval=0.05) +paused = False + bass_track = mixer.Sound(file='test_data/bass.wav') drums_track = mixer.Sound(file='test_data/drums.wav') vocals_track = mixer.Sound(file='test_data/vocals.wav') @@ -81,7 +87,28 @@ vocals_pixel.fill((0,0,vocals_color)) other_pixel.fill((other_color, other_color, 0)) +print(pedal_pressed.fell) + while mixer.get_busy(): + pedal_pressed.update() + if pedal_pressed.short_count: + if not paused: + mixer.pause() + paused = True + print("Pause") + else: + mixer.unpause() + paused = False + print("Unpause") + if pedal_pressed.long_press: + print("long press") + mixer.stop() + bass_track.play() + drums_track.play() + vocals_track.play() + other_track.play() + + #0: Drums # negate the position to make clockwise rotation positive drums_position = -drums_encoder.position @@ -167,9 +194,10 @@ if other_button.value and other_button_held: other_button_held = False -other_volume_before_mute=other_track.get_volume() -other_track.set_volume(0) +drums_pixel.fill((0,0,0)) +bass_pixel.fill((0,0,0)) +vocals_pixel.fill((0,0,0)) +other_pixel.fill((0,0,0)) -print(mixer.get_num_channels()) mixer.quit() diff --git a/imitator/yt_demuc/requirements.txt b/imitator/yt_demuc/requirements.txt index 283296f..b951a86 100644 --- a/imitator/yt_demuc/requirements.txt +++ b/imitator/yt_demuc/requirements.txt @@ -1,3 +1,3 @@ click==8.1.3 demucs==4.0.1 -yt-dlp==2024.7.1 +yt-dlp==2024.7.1 \ No newline at end of file diff --git a/sodio/README.md b/sodio/README.md deleted file mode 100644 index 238f5aa..0000000 --- a/sodio/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Sodio - -## Compresor - -## Descripción - -Este es el primer pedal diseñado por encargo de un cliente, y existe mucha distancia física entre el taller y el cliente, por lo cual es necesario crear un diseño que sea muy versatil y modular. - -De forma similar al famoso compresor LA2, utiliza un panel luminoso (LA2: EL Wire a alto voltaje) para emitir la señal recibida por la guitarra o entrada, y unas fotoceldas para capturar dicha señal. - -En nuestro caso vamos a utilizar un [panel de backlight](https://www.adafruit.com/product/1622) y [fotodiodos](https://www.microjpm.com/products/ad35088/) para actualizar el proyecto con componentes modernos, útiles a bajos voltajes. - -También se utilizan transistores en algunos casos, y potenciómetros digitales en otros casos, para permitir cambiar entre diferentes versiones del circuito, tratando de eliminar decisiones que debe tomar el ingenierio al diseñar el circuito, que limitan la utilidad del pedal. Por ejemplo algo tan sencillo como los capacitores de entrada, los cuales definen si el pedal es útil para bajo o guitarra, pero limitan instrumentos como guitarras de 7 cuerdas o barítonas. - -Para control se piensa usar una Clue para control vía bluetooth. Para esto se va a utilizar un conector [para Microbit](https://www.adafruit.com/product/3888 para control vía bluetooth. Para esto se va a utilizar un conector [para Microbit](https://www.adafruit.com/product/3888). - -TODO: -- [x] Prueba básica de circuito -- [ ] Compra de backlight -- [ ] Diseño de PCB -- [ ] Código mínimo para pantalla y control vía bluetooth