Teensy Audio Board: Odtwarzacz kolęd pod choinkę

miniHo ho ho! Idą święta, a w raz z nimi choinka, prezenty pod nią oraz kolędy. Zaprzęgnijmy więc dziś Teensy i Audio Boarda do pracy, aby zagrał nam pod choinką trochę świątecznych kolęd :)

Co będzie nam potrzebne?

Jak podłączyć?

Przyciski, które będą odpowiadały za funkcje graj/pauza, poprzedni utwór, następny utwór podłączamy kolejno do pinów 0, 1 i 2 tak, aby po wciśnięciu na tych pinach pojawiła się masa. Zasilanie (VCC) konwertera I2C, a zarazem ekranu podłączamy do pinu VIN (na którym przy zasilaniu z USB otrzymamy 5 V). Piny danych (SDA) i zegara (SCL) podłączamy do pinów 18 i 19 w Teensy. Powinno to wyglądać tak:

koledy

Jeśli w Teensy mamy wlutowane krótkie męskie piny to po podłączeniu Audio Boarda możemy mieć problem znaleźć miejsce, gdzie łatwo byłoby się wpiąć kabelkami. Polecam odprasować sobie przejściówkę, która umożliwi nam wpięcie w nią Teensy, pod spodem Audio Boarda i będziemy mieli wyprowadzone goldpiny obok Teensy. Pliki EAGLE można pobrać tutaj.

Kod programu

Cały kod programu do pobrania tutaj.

Jak widać część kodu (np. funkcja, która pobiera listę plików dźwiękowych z karty) jest zapożyczona z jednego z poprzednich artykułów :)

Na początku inicjujemy sobie kilka potrzebnych później zmiennych, obiektów klasy Bounce (do obsługi przycisków) oraz obiekt odpowiedzialny za obsługę wyświetlacza z konwerterem I2C. W funkcji setup nie dzieje się nic niezwykłego. Ustawiamy piny, wyświetlacz oraz kartę SD i wywołujemy funkcję, która pobierze listę plików .wav na karcie SD.

Właściwie jedyną funkcją, która będzie wymagała dziś głębszego omówienia jest loop. Podzielmy sobie ją na 3 fragmenty, które po kolei wyjaśnię.

Automatyczne odtwarzanie kolejnego pliku po skończeniu aktualnego

  if(!isPaused && !sdwav.isPlaying()) {
    currentFile++;
    currentFile %= filesCount;
    playSound(currentFile);
  }

Zmienna logiczna isPaused informuje nas, czy odtwarzanie zostało przerwane przez użytkownika, natomiast metoda isPlaying zwraca true, jeżeli muzyka gra, a false jeżeli nie. Łatwo teraz napisać warunek, że jeżeli użytkownik nie przerwał odtwarzania samemu, a muzyka nie gra to zwiększamy indeks aktualnego pliku o 1, sprawdzamy, czy nie wyszedł poza zakres i wywołujemy funkcję, która odtworzy plik audio.

Wyświetlanie postępu odtwarzania pliku

  if(sdwav.isPlaying()) {
    int total_s = sdwav.lengthMillis() / 1000;
    int elapsed_s = sdwav.positionMillis() / 1000;
    int total_m = total_s / 60;
    int elapsed_m = elapsed_s / 60;

    total_s -= total_m * 60;
    elapsed_s -= elapsed_m * 60;

    lcd.setCursor(0,1);
    if(elapsed_m < 10) lcd.print("0");
    lcd.print(elapsed_m);
    lcd.print(":");
    if(elapsed_s < 10) lcd.print("0");
    lcd.print(elapsed_s);
    lcd.print(" / ");
    if(total_m < 10) lcd.print("0");
    lcd.print(total_m);
    lcd.print(":");
    if(total_s < 10) lcd.print("0");
    lcd.print(total_s);
  }

W tym fragmencie kodu sprawdzamy, czy muzyka gra. Jeżeli tak to pobieramy informacje o czasie trwania utworu (w milisekundach), oraz ile milisekund upłynęło od początku pliku dźwiękowego. Następnie dzielimy te wartości przez 1000, aby otrzymać wyniki w sekundach. Teraz możemy taką liczbę sekund podzielić całkowicie przez 60, co da nam liczbę minut, a następnie odjąć ilość minut * 60 od całkowitej ilości sekund i takim sposobem otrzymujemy w jednej zmiennej liczbę minut, a w drugiej liczbę sekund. Teraz wystarczy odpowiednio sformatować wynik i wypisać go na ekranie w postaci MM:SS / MM:SS.

Obsługa przycisków play/pause, prev oraz next

  if(!bouncePlay.update() && !bouncePrev.update() && !bounceNext.update()) return;
  
  if(bouncePlay.fallingEdge()) {
    if(sdwav.isPlaying()) {
      lcd.clear();
      sdwav.stop();
      isPaused = true;
    } else {
      playSound(currentFile);
    }
  } else if(bouncePrev.fallingEdge()) {
    currentFile--;
    if(currentFile < 0) currentFile = filesCount - 1;
    playSound(currentFile);
  } else if(bounceNext.fallingEdge()) {
    currentFile++;
    currentFile %= filesCount;
    playSound(currentFile);
  }

W ostatnim fragmencie sprawdzamy, czy któryś z przycisków zmienił swój stan. Jeżeli nie, to wychodzimy z funkcji. Jeżeli tak to musimy obsłużyć każdy z przycisków.

Na początek przycisk play/pause. Jeżeli muzyka gra, to ją zatrzymujemy. Jeżeli nie gra, to zaczynamy grać. Proste :)

Przyciski prev i next wyglądają podobnie, tj. zmniejszamy lub zwiększamy indeks odtwarzanego pliku, sprawdzamy, czy nie indeks nie wyszedł poza zakres (czyli w przypadku prev mniej niż 0 lub w przypadku next więcej niż filesCount – 1).

To wszystko :) Teraz wystarczy wgrać kolędy w formacie .wav 16 bit PCM 44100 Hz. Pliki takie możemy przygotować sobie w darmowym programie Audacity. Wystarczy w lewym dolnym rogu okna ustawić próbkowanie projektu na 44100 Hz, a następnie wybrać Plik > Eksportuj dźwięk… po czym w polu wyboru typu pliku wybieramy 16-bitowe PCM WAV (Microsoft). Teraz wystarczy zapisać i plik gotowy :)

Kiedy przygotujemy już wszystkie pliki możemy wgrać je na kartę SD, włożyć ją do Audio Boarda i kolędować razem z Teensy.

dsc_0281