Ζήτησα από τον Claude να σχεδιάσει μια λύση για ένα από τα πιο δύσκολα ζητήματα που οι μηχανικοί του Audio DSP συχνά κάνουν λάθος, το οποίο είναι αρκετά δύσκολο για τους ανθρώπους να αντιμετωπίσουν. Δημιουργήστε ένα παράδειγμα ενός ισοσταθμιστή στην C++ που παίρνει το pinout ενός πίνακα πληροφοριών και εφαρμόζει τις αρχές ser/des (serialization/deserelization) για να συγχρονίσει byte-byte σε σχεδόν πραγματικό χρόνο ροές ήχου και βίντεο που προέρχονται από κανάλια διαφοράς. Δημιουργήστε ένα παράδειγμα ενός ισοσταθμιστή στην C++ που παίρνει το pinout ενός πίνακα πληροφοριών και εφαρμόζει τις αρχές ser/des (serialization/deserelization) για να συγχρονίσει byte-byte σε σχεδόν πραγματικό χρόνο ροές ήχου και βίντεο που προέρχονται από κανάλια διαφοράς. Ενώ υπάρχει κάποιο είδος τεχνικής γνώσης και επίπεδο ειδικότητας, τα αποτελέσματα είναι εντυπωσιακά, Αυτός είναι επίσης ο λόγος για τον οποίο η αποκέντρωση είναι σημαντική για το μέλλον της γλώσσας ως ένα άλλο στρώμα αφαίρεσης για τον κώδικα (όπως αναφέρθηκε στο τελευταίο μου άρθρο). readable code based off of a problem that most humans don’t get right Αυτό που λέμε, εδώ είναι μια βόλτα μέσα από αυτό που δημιούργησε ο Claude. Βήμα 1: Εισαγωγή βιβλιοθηκών #include <thread> #include <atomic> #include <array> #include <cstring> #include <cmath> using namespace std; Το δεύτερο βήμα που ήταν η διαμόρφωση του pinout δεν είναι πολύ δύσκολο. Γνωρίζοντας πώς να χρησιμοποιήσετε το hex και τον ήχο εισόδου / εξόδου καθώς και το βίντεο εισόδου / εξόδου είναι κάτι που δεν είναι δύσκολο για έναν άνθρωπο να κάνει. Βήμα 2: Διαμόρφωση του Pinout / Infotainment board pinout configuration struct Pinout { uint8_t audio_in, video_in, audio_out, video_out, clk, sync; } pins = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20}; Επόμενο είναι η ρύθμιση του buffer και το Copilot ρυθμίζει ένα κυκλικό buffer για την ροή δεδομένων. Βήμα 3: Ρυθμίστε το buffer // Circular buffer for lock-free streaming template<size_t N> struct RingBuf { array<uint8_t, N> data; atomic<size_t> wr{0}, rd{0}; void write(uint8_t b) { data[wr++ & (N-1)] = b; } uint8_t read() { return data[rd++ & (N-1)]; } }; Μετά από αυτό είναι η σειριοποίηση και η απεριορισμός μαζί με τη χρήση bitwise χειριστών για τη συσκευασία (η οποία γίνεται δύσκολη). Βήμα 4: Ser/Des διαμόρφωση // Serialize/deserialize with bitwise packing uint32_t serialize(uint8_t* bytes, size_t n) { uint32_t v = 0; for(size_t i = 0; i < n; ++i) v |= bytes[i] << (i*8); return v; } void deserialize(uint32_t v, uint8_t* out, size_t n) { for(size_t i = 0; i < n; ++i) out[i] = (v >> (i*8)) & 0xFF; } Και τώρα ξέρει πώς να προσομοιώνει τις ζώνες εξισορρόπησης και την απόκρυψη για διαφορετικές συχνότητες. Βήμα 5: Ρυθμίστε τις ζώνες εξισορρόπησης και τη μάσκα // Equalizer bands using bitwise freq masking void equalize(uint8_t* audio, size_t n, uint8_t gain_mask) { for(size_t i = 0; i < n; ++i) { uint8_t sample = audio[i]; uint8_t low = (sample & 0x0F) * ((gain_mask >> 0) & 0x3) / 2; uint8_t mid = ((sample >> 2) & 0x0F) * ((gain_mask >> 2) & 0x3) / 2; uint8_t high = ((sample >> 4) & 0x0F) * ((gain_mask >> 4) & 0x3) / 2; audio[i] = (high << 4) | (mid << 2) | low; } } Τώρα είναι η ροή Byte-by-Byte και είναι σε θέση να κοιμάται ανάμεσα στα νήματα, έτσι ώστε τα bytes να μην επικαλύπτονται. Βήμα 6: Streaming byte-by-byte // Sync byte-by-byte stream processing void process_stream(RingBuf<4096>& in_buf, RingBuf<4096>& out_buf, uint8_t pin, atomic<bool>& run, bool is_audio) { uint8_t chunk[4], processed[4]; while(run) { if((in_buf.wr - in_buf.rd) >= 4) { // Wait for 4-byte chunk for(int i = 0; i < 4; ++i) chunk[i] = in_buf.read(); uint32_t packed = serialize(chunk, 4); if(is_audio) { equalize(chunk, 4, 0b11011001); } // EQ with gain pattern else { for(int i = 0; i < 4; ++i) chunk[i] ^= 0xAA; } // Video sync pattern XOR deserialize(serialize(chunk, 4), processed, 4); for(int i = 0; i < 4; ++i) out_buf.write(processed[i] | (pin & 0x01)); // Pin sync bit } this_thread::sleep_for(chrono::microseconds(10)); // ~100KB/s throughput } } Τέλος, είναι η διαμόρφωση και τροφοδοσία στα νήματα. Βήμα 7: Διαμόρφωση συνδέσμων int main() { RingBuf<4096> audio_in, audio_out, video_in, video_out; atomic<bool> running{true}; // Spawn I/O threads for audio and video channels thread t1(process_stream, ref(audio_in), ref(audio_out), pins.audio_in, ref(running), true); thread t2(process_stream, ref(video_in), ref(video_out), pins.video_in, ref(running), false); // Simulate input streams (normally from hardware) thread feeder([&]() { uint8_t a = 0, v = 0; while(running) { audio_in.write(a++); video_in.write(v++); this_thread::sleep_for(chrono::microseconds(50)); } }); this_thread::sleep_for(chrono::seconds(2)); // Run for 2 seconds running = false; t1.join(); t2.join(); feeder.join(); return 0; } Τα βήματα 5 έως 7 είναι τα πιο εντυπωσιακά, ειδικά δεδομένου ότι υπάρχει διάκριση μεταξύ πραγματικού χρόνου και σχεδόν πραγματικού χρόνου συγχρονισμού, καθώς και από προεπιλογή γνωρίζοντας τι δεν πρέπει να κάνετε για να επικαλύπτονται τα ρεύματα. this_thread::sleep_for(chrono::microseconds(10)); Είναι μια πολύ λογική απόφαση που θα έπρεπε να έχει ληφθεί από έναν άνθρωπο. Η πραγματικότητα είναι, δεν ήταν, και αυτό είναι ακριβώς το είδος του bot που αναλαμβάνει τους ρόλους των νεότερων και ανώτερων προγραμματιστών. Ωστόσο, αν καταλάβετε πώς να προτρέψετε και πώς να χειριστείτε, τότε τα bots δεν θα πάρουν τη δουλειά σας. θα το ενισχύσουν μόνο. Υπήρξε μια εποχή που πολλοί πίστευαν ότι οι υπολογιστές θα εξαλείψουν την ανάγκη για μαθηματικούς, και όλοι γνωρίζουμε πώς αυτό αποδείχθηκε. Αν σας άρεσε αυτό το άρθρο, φροντίστε να μου στείλετε μια πρόσκληση στο ή να μας ακολουθήσει όπου μπορείτε να δείτε πολλά από τον ανθρώπινο κώδικα μου. Μέχρι την επόμενη φορά, να έχετε μια διασκεδαστική Hackernoon. Λίνκινγκ Το Github