私はクロードに、オーディオDSPエンジニアがしばしば間違っている最も困難な問題の1つを解決するためのソリューションを提案するように依頼しました。 インフォテインメントボードのピノートをとり、ser/des(serialization/deserelization)原則を適用して、ほぼリアルタイムのオーディオストリームと差異チャンネルから来るビデオのバイトごとにバイトを同期します。 インフォテインメントボードのピノートをとり、ser/des(serialization/deserelization)原則を適用して、ほぼリアルタイムのオーディオストリームと差異チャンネルから来るビデオのバイトごとにバイトを同期します。 ある種の技術的知識と特定性のレベルがあるにもかかわらず、結果は驚異的です。 これはまた、コードのもう一つの抽象層としての言語の将来にとって、分散化が重要な理由でもある(私の最後の記事で述べたように)。 readable code based off of a problem that most humans don’t get right 言い換えれば、ここでは、クロードが生み出したものについての一歩一歩です。 ステップ1:図書館の輸入 #include <thread> #include <atomic> #include <array> #include <cstring> #include <cmath> using namespace std; ピノートを構成するための2番目のステップはあまり難しいものではありません。 ヘックスとオーディオの入力/出力、およびビデオの入力/出力を使用することを知ることは、人間にとって難しいことではありません。 Step 2: Configure the 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}; 次にバッファを設定し、Copilot はデータ ストリーム用の円バッファを設定します。 STEP 3: バッファを設定する // 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)]; } }; その後、シリアリングとデセリアリングと、パッケージのためのビットウィーズオペレーターの使用(困難になる)があります。 ステップ4: Ser/Des Configuration // 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; } そして今では、バンドをシミュレートし、異なる周波数をマスクする方法を知っています。 Step 5: Set Equalizer Bands and Masking // 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のストリーミングであり、バイトが重複しないようにトレード間で眠ることができます。 Step 6: 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 } } 最後に、構成とフードの供給です。 STEP 7: Configure Threads 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)); それは非常に論理的な決定であり、人間によって作られたはずです。現実は、それはそうではありませんでした、そしてこれはまさにジュニアおよびシニア開発者の役割を引き継いでいるボットの種類です。しかし、あなたがプロンプトやデバッグの方法を理解するならば、ボットはあなたの仕事を取らないでしょう。それらは単にそれを向上させます。多くの人がコンピュータが数学者の必要性を排除すると信じた時があり、私たちはすべてがその結果を知っています。 あなたがこの記事を気に入った場合は、私に招待状を送信してください あるいは私にフォローしてください。 私の人間のコードをたくさん見ることができますので、次回まで、楽しいハッカーナイトをお過ごしください。 リンク GitHub