Jak z Fuzz Factory zrobić Fat Pig Factory.

Pożyczyłem do potestowania Big Muff Germanium 4 i spodobało mi się brzmienie tranzystorów germanowych, ale… ceny tych efektów to jakiś absurd. Postanowiłem zbudować coś sam i wybór padł na klona Fuzz Factory od Musikding. Genialny zestaw DIY zawierający wszystko co potrzeba. Musiałem tylko dokupić u nich obudowę i gałki potencjometrów.

Zmontowałem w dwa wieczory, świetna zabawa i co ciekawe zadziałało przy pierwszym uruchomieniu. Muszę przyznać, że to chyba najciekawszy efekt gitarowy jaki kiedykolwiek widziałem. Można ukręcić naprawdę oryginalne gitarowe i zupełnie niegitarowe brzmienia. Ale właśnie, jeśli chodzi o brzmienie – dźwięk jest raczej w zakresie średnich i wysokich częstotliwości, a ja lubię warczące i burczące fuzzy, jak u Ariela Posena… Dodatkowo, efekt sam z siebie popierdywał dziwnym szumem, jakby ładujący się i rozładowywujący kondensator. Takie pyr, pyr, pyr…

Gdzieś obiło mi się o uszy, że problem może wynikać z impedancji wejściowej, więc popatrzyłem na schematy innych podobnych efektów. Np. Tone bender ma na wejściu 100k rezystor. Muff ma coś na każdym stopniu wzmocnienia (ok. 60k na pierwszym). Fuzz Face… nic. Fuzz Factory. Też nic.

Wlutowałem najpierw 100k. Cisza, zero zakłóceń. Tylko biały szum od tranzystorów. Ale oscylacji jakby mniej, więc drugie co mi wpadło w ręce – 1.5 kilo omów – okazuje się, że to wystarczy. Cisza. Spokój. Słowa opisujące marzenia sąsiadów.

Druga zmiana to basy, a raczej ich brak. Wg schematu Musikding kondensator C2 to 100nF (0.1uF). Zmieniłem na 680nF. Wow! Można ten układ wprowadzić w oscylację, która brzmi jak gitara basowa.

Trzecia zmiana – pierwszy stopień, tranzystor Q1 (2N3904) zamieniłem na germanowy AC176K NPN i dwa pozostałe to też germanowe AC125 PNP.

Wyszła kostka, która ma zarówno mnóstwo basu oraz górę i warczący distortion.

I na koniec – ponoć układy o topologii „fuzz face” muszą być pierwsze w łańcuchu efektów. U mnie będzie na drugim miejscu, bo doładowanie Pig Factory overdrivem Mojo Mojo od TC Electronics to jest coś, czego bardzo długo szukałem. No i skręcenie głośności w gitarze, nawet z overdrive z przodu przy odpowiednio dobranym poziomie głośności, czyści brzmienie. Chociaż nic mi się tak nie podoba jak doładowane, mocno przesterowane tranzystory germanowe.

Próbka 1, Próbka 2.

Sway w Waylandzie zamiast X-ów.

Z X Window System szedłem przez życie, ale odkąd pierwszy raz przeczytałem o Wayland, od czasu do czasu sprawdzałem postępy w tym projekcie. Nie, żebym miał jakieś wielkie „ale” do X-ów, jednak na moje niewielkie potrzeby ta armata zawsze wydawała mi się zbyt wielkiego kalibru.

Mijały lata, zawsze czegoś jednak brakowało. Na początku duże „desktopy” jeszcze Wayland nie wspierały, później moja karta graficzna niezbyt działała (NV3100m, bo lubię stare laptopy). Aż w końcu nouveau i kernel polubiły się z moim retro-sprzętem i jest:

Najbardziej zaskoczył mnie sway. Złapał „w locie” moją konfigurację i3 na tyle skutecznie, że musiałem sie upewnić, czy to na pewno sway.

Fujinet-pc na Raspberry Pi Zero W.

Trafiłem ostatnio na wątek forum Atari Age, w którym Jan Krupa (apc) informował o postępach prac nad jego portem Fujinet na PC. Pierwsza myśl – jakby to działało na RPi Zero W?

Zamówiłem, szybko dotarło. Dopracowane jako produkt genialnie.

Instalacja Arch Linux na Arm6 to jakieś 10 minut na przygotowanie karty i konfigurację Wifi. Konfiguracja distcc zajmuje trochę dłużej, ale działa i bez tego – kompilacja na Raspberry to jakieś 15 minut. Źródła kompilują się bez żadnych warningów (zależności są minimalne: gcc, cmake, make i libbsd).

Update (sierpień 2022):

Niestety Archlinux Arm porzucił wparcie dla Arm6, więc przeinstalowałem Fujinet na Raspberry Pi OS z Debianem 11.4 Bullseye. Działa tak samo pięknie, a może nawet nieco lepiej.

Zwykle uruchamiam Fujinet w sesji screen przy starcie Raspberry Pi: screen -d -m ./run-fujinet, bo w razie konieczności zawsze można się przypiąć i odpiąć screenem po zalogowaniu przez ssh żeby zobaczyć co się dzieje. Interfejs webowy pozwala też na reset fujinet, ale szybciej i wygodniej zrobić to z Termux Widget na telefonie (skrypty uruchamiane są via ssh na Raspberry Pi):

#!/bin/bash
killall -9 fujinet
cd /home/greblus/fujinet/
screen -d -m ./run-fujinet

Skoro działa, to może jakiś niezbyt miarodajny test, np. RWTEST. Testy w SpartaDos X na Rpi, laptopie z Linuksem i w moim porcie AspeQt na Androidzie. Ten sam obraz atr z RWTEST.COM podmontowany jako D1. Fujinet na Rpi Zero działa fajnie z hsindex=0 i SIO2PC-USB, ale dobrze jest wyjście debuggowania w skrypcie run-fujinet przekierować do /dev/null, jest jednak nieznacznie szybciej, nawet przy odpiętym terminalu screen.

Fujinet na Rpi Zero W
Fujinet na laptopie
AspeQt na Androidzie

Jest ok. Zaskakujące, że na PC działa wolniej. Tłumaczę sobie to tym, że odczyty realizowane są z pamięci RAM bo obraz atr jest wczytywany do pamięci, a zapisy na Rpi i Androidzie realizowane są na pamięci Flash, tymczasem na moim starym laptopie kręci się stary dobry dysk talerzowy 5400rpm 🙂

auto&&… args.

Kiedyś zastanawiałem się nad tym, co jeszcze można będzie zrobić z auto? Auto może być użyte do dedukcji typów uniwersalnych referencji pakietu parametrów, w funkcjach o dowolnej liczbie parametrów. Brzmi strasznie ale wbrew pozorom nie jest to takie skomplikowane:

#include <iostream>

using namespace std;

int main()
{
        auto f = [] (auto ... args) {
            ((cout << args << " "), ...);
            cout << endl;
        };

        f(1, 2.3, "cztery");
}

~/cpp_fun>$ ./”variadic_lambdas1″
1 2.3 cztery

Niedługo mam nadzieję będzie to działać nie tylko dla funkcji lambda, ale też dla „zwykłych” funkcji.

std::variant, std::any i ranges-v3 czyli prawie jak w Pythonie.

Ostatnio w ramach „się odstresowywania” czytam sobie o zmianach w standardzie c++17 i c++20 (wielkie dzięki Bartkowi Filipkowi za jego bloga). Dużo tego, ale zmiany są ogromne i dzisiejszy C++ jest po prostu fascynujący. Nawet nie komentuje poniższego kodu. Wklejam tu dla samego siebie i powiem tylko, że jak g++/clang++ będą z c++20 zgodne, to ja już nie chcę nic więcej. Może jeszcze tylko ogarnięcie parallelstl. Intel-tbb działa pięknie. Tylko jeden cytat apropos:

„Do you know how much of the processing power of a typical desktop machine we can utilize using only the core version of C++/Standard Library? 50%, 100%? 10%?[…] we can usually access only around 0,25% with single-threaded C++ code and maybe a few percent when you add threading from C++11/14.” (Sean Parent).

Przyznam szczerze, że nieco otworzyło mi to oczy:

GPU power CPU vectorization CPU threading Single Thread
75% 20% 4% 0,25%
#include <iostream>
#include <vector>
#include <variant>
#include <any>

using namespace std;

template <typename T1, typename T2>
class T {
    T1 a; T2 b;    
    public:
    T(T1 a, T2 b) : a(a), b(b) {}
    void show() {        
        cout << a << b;
    }    
};

int main() {
    T<char, const char*> t1('C', "++");
    T<int, const char*> t2(17, " nie taki straszny ;)\n");
    T<string, int> t3("66.", 6);

    typedef variant<T<char, const char*>, T<int, const char*>, T<string, int>> var_t;
    vector<var_t> var_v {t1, t2, t3};

    auto callShow = [](auto& obj) { obj.show(); };

    for (auto& obj : var_v)
        std::visit(callShow, obj);   

    cout << endl << "------" << endl;

    vector<any>anyv {1, 2.0, "trzy"};

    for(auto &i: anyv) {
        if (i.type() == typeid(int))
            cout << any_cast<int>(i) << endl;     
        if (i.type() == typeid(double))
            cout << any_cast<double>(i) << endl;     
        if (i.type() == typeid(const char *))
            cout << any_cast<const char *>(i) << endl;   
        if (i.type() == typeid(string))
            cout << any_cast<string>(i) << endl;    
    }
}

PS E:\cpp_fun> .\templ1.exe
C++17 nie taki straszny 😉
66.6
——
1
2
trzy

#include <iostream>
#include <range/v3/all.hpp> 
#include <string>
#include <vector>

using namespace std;
using namespace ranges;

int main()
{
    auto print = [](auto &i) {cout << i << " "; };    
    auto even = [](int i){ return 0 == i % 2; };
    auto square = [](int i) { return i * i; };
    auto end = ranges::end;

    vector<int> ints = views::ints(1, 50)  | views::filter(even) | 
                       views::transform(square) | views::slice(end-5, end) | 
                       ranges::to<vector>();

    ranges::for_each(ints, print);

    auto chars = views::iota('a', 'z'+1) | views::reverse
                       | ranges::to<vector>();
    
    ranges::for_each(chars, print);

    auto t = views::ints(0, 50) | 
         views::filter([](int i) { return i<20 ? true : false; }) | 
         ranges::to<vector>();
    
    ranges::for_each(t, print);
    cout << endl;    
}

PS E:\cpp_fun> .\ranges2.exe
1600 1764 1936 2116 2304 z y x w v u t s r q p o n m l k j i h g f e d c b a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

BTW: dzięki Bartkowi odkryłem, że nie boję się już lambd, a nawet je trochę lubię 😉

Flutter for the Web.

Flutter for the Web

Aplikacje Flutter w przeglądarce? Właśnie na Google Developers Days pojawiło się info o tym, że Flutter for the Web znalazło się w głównym repozytorium. Wystarczy zmienić flutter channel ze stable na master aby zgodnie z opisem tutaj odpalić aplikację w przeglądarce.  Drugi brakujący feature: Foreign Function Interface (FFI). Przyznam szczerze – te zmiany robią wrażenie. Kawał ciekawej i przydatnej technologii. Jedno jest pewne – będzie się działo!

Flutter for the Desktop

Dart i Flutter.

Fajny ten Dart. Jakoś wcześniej nie mogłem się do niego przekonać, ale moje ostatnie eksperymenta z ES6 trochę mi to ułatwiły.

Analizator i system typów robi spore wrażenie. OOP w Dart to chyba najlepsze co do tej pory widziałem – dziedziczenie, interfejsy, klasy i metody abstrakcyjne, mixins, overrides, listy inicjalizacyjne konstruktora, prosta inicjalizacja argumentów nazwanych konstruktora, po prostu trzeba to zobaczyć. Flutter to temat na kilka osobnych wpisów ;), a StatefullWidget mnie zachwycił. Poniżej mój pierwszy eksperyment – kolejne wcielenie apki do sterowania esp8266 za pomocą http request.

Kliknij w obrazek powyżej żeby zobaczyć plik źródłowy.Widać w tym przyszłość i to raczej pozytywną, zarówno dla użytkowników, jak i programistów. A i jeszcze jedno – nie sądziłem, że to kiedyś powiem, ale Visual Studio Code to świetny edytor ;).

Aktualizacja: oficjalnie zaliczam Dart i Flutter do grona zjawisk i technologii, które mnie zafascynowały (patrz strip na górze ;)).

Kliknij w obrazek powyżej żeby zobaczyć plik źródłowy.

Syncthing + AspeQt-1.0.62.

Z najnowszej wersji AspeQt-1.0.62 (dostępna w Google Play i na Github) jestem wyjątkowo dumny pomimo, że nie ma w niej żadnych rewolucyjnych zmian:

  • Przebudowane z Qt-5.9.7 (min. API 16 = Android 4.1).
  • Poprawione błędy sterownika ftdi – działa z HSINDEX 0 = 115200bps.
  • Sprawdzanie dostępu do karty SD na Mashmallow i nowszych wersjach Androida

Jednak ta druga pozycja… to chyba najbardziej dołujący jak dotąd błąd z jakim przyszło mi się zmierzyć. Ale o co chodzi? Na nie-rootowanym Androidzie jedyna sensowna opcja obsługi portu szeregowego, a taki jest potrzebny do emulacji urządzeń SIO w 8-bitowym Atari, to tzw. usb-host mode i próba dogadania się z najpopularniejszym i najbardziej sensownym układem pozwalającym na taką komunikację, czyli FT232R firmy FTDI. Firma wypuściła w tym celu bibliotekę d2xx dla Androida, jednak nie jest ona zbyt szybka, a dodatkowo, licencja jest co najmniej problematyczna. Dawno temu odkryłem więc usb-serial-for-android. Dostęp do obiektów Javy w Qt5 i vice versa opisywałem już wcześniej – wystarczy wspomnieć, że bez JNI nie da rady tego ogarnąć, ale co zaskakujące, działa to bardzo szybko i wydajnie. Pod warunkiem, że działa ;). No i tu zaczyna się demotywująca część historii. Na niektórych urządzeniach AspeQt śmigał aż miło, ale użytkownicy zaczęli zgłaszać, że pomimo prawidłowej obsługi usb-host, na niektórych całkiem porządnych urządzeniach z Androidem nie działa. Niestety usb-serial-for-android od dwóch lat praktycznie rozwija tylko jedna osoba – Kai Morich w swoim forku – i to dzięki niemu udało się problem rozwiązać.

A teraz o moim ostatnim odkryciu: syncthing. AspeQt z HSINDEX 0 śmiga całkiem szybko, więc podmontowałem w nim na androidowym TVBoxie katalog, który przez syncthing jest synchronizowany po Wifi z laptopem i telefonem. Dzięki temu wszystko co ściągnę z internetów mogę od razu, bez skomplikowanych operacji, uruchomić na moim 8-bitowym super sprzęcie ;). Syncthing jest świetny, darmowy i bez reklam. W archowych repozytoriach są gotowe paczki dla Linuksa, a w Google Play apk dla Androida. Długo czegoś takiego szukałem: