Membuat Efek Gema

[Fitur yang terkait dengan halaman ini, Pemutar Media Windows SDK, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer. MediaPlayer telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer alih-alih Pemutar Media Windows SDK, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

Anda harus terlebih dahulu menghapus kode dari sampel wizard yang menskalakan audio. Dari bagian 8-bit, hapus kode berikut:

// Apply scale factor to sample.
i = int( ((double) i) * m_dwDelayTime );

(Ingat bahwa m_fScaleFactor digantikan oleh m_dwDelayTime.)

Dari bagian 16-bit, hapus kode berikut:

// Apply scale factor to sample.
i = int( ((double) i) * m_dwDelayTime );

Implementasi DoProcessOutput yang disediakan oleh kode sampel wizard plug-in membuat perulangan sementara yang berulang satu kali untuk setiap sampel dalam buffer input yang disediakan oleh Pemutar Media Windows. Perulangan ini berfungsi dengan cara yang sama untuk audio 8-bit dan 16-bit, meskipun perulangan terpisah diperlukan untuk masing-masing. Dalam setiap kasus, perulangan dimulai dengan pengujian berikut:

while (dwSamplesToProcess--)

Setelah berada di dalam perulangan, rutinitas pemrosesan sangat mirip untuk audio 8-bit dan 16-bit. Perbedaan utamanya adalah bahwa kode di bagian 8-bit mengubah rentang nilai data menjadi -128 hingga 127, dan kemudian mengonversi rentang kembali sebelum menulis data ke buffer output. Ini penting untuk mempertahankan simetri bentuk gelombang audio selama pemrosesan.

Sekarang Anda dapat mulai menambahkan dan mengganti kode dalam perulangan pemrosesan.

Mengambil Sampel dari Buffer Input

Selama setiap iterasi perulangan, satu sampel diambil dari buffer input. Untuk audio 8-bit, sampel digeser ke rentang baru, lalu pointer ke buffer input dimajukan ke sampel berikutnya. Kode berikut berasal dari wizard plug-in:

// Get the input sample and normalize to -128 .. 127
int i = (*pbInputData++) - 128;

Untuk audio 16-bit, prosesnya sama kecuali untuk normalisasi:

// Get the input sample.
int i = *pwInputData++;

Ingatlah bahwa pointer dalam kode 16-bit telah dikonversi ke jenis pendek.

Mengambil Sampel dari Penyangga Penundaan

Selanjutnya, ambil satu sampel dari buffer penundaan. Untuk kode 8-bit, sampel penundaan disimpan dalam kisaran asli 0 hingga 255. Kode berikut, yang harus Anda tambahkan, mengambil sampel penundaan 8-bit:

// Get the delay sample and normalize to -128 .. 127
int delay = m_pbDelayPointer[0] - 128;

Untuk audio 16-bit, prosesnya serupa:

// Get the delay sample.
int delay = *pwDelayPointer;

Menulis Sampel Input ke Buffer Penundaan

Sekarang, Anda harus menyimpan sampel input dalam buffer penundaan di lokasi yang sama tempat Anda mengambil sampel penundaan. Berikut ini adalah kode yang harus Anda tambahkan untuk audio 8-bit:

// Write the input sample into the delay buffer.
m_pbDelayPointer[0] = i + 128;

Ini adalah kode yang akan ditambahkan untuk bagian 16-bit:

// Write the input sample to the delay buffer.
*pwDelayPointer = i;

Memindahkan Penunjuk Buffer Tunda

Sekarang setelah pekerjaan dalam buffer penundaan selesai untuk iterasi ini, Anda dapat memajukan pointer bergerak ke buffer penundaan. Jika pointer mencapai akhir buffer melingkar, Anda harus mengubah nilainya untuk menunjuk ke kepala buffer. Untuk melakukan ini untuk audio 8-bit, gunakan kode berikut:

// Increment the delay pointer.
// If it has passed the end of the buffer,
// then move it to the head of the buffer.
if (++m_pbDelayPointer > pbEOFDelayBuffer)
    m_pbDelayPointer = m_pbDelayBuffer;

Berikut adalah kode untuk bagian 16-bit:

// Increment the local delay pointer.
// If it is past the end of the buffer,
// then move it to the head of the buffer.
if (++pwDelayPointer > pwEOFDelayBuffer)
    pwDelayPointer = pwDelayBuffer;

Karena pointer di bagian 16-bit benar-benar salinan variabel anggota, Anda harus ingat untuk memperbarui nilai dalam variabel anggota dengan alamat baru. Jika Anda gagal melakukan ini, penunjuk buffer penundaan akan menunjuk ke kepala buffer berulang kali dan efek gema Anda tidak akan berfungsi seperti yang diharapkan. Tambahkan kode berikut ke bagian 16-bit:

// Move the global delay pointer.
m_pbDelayPointer = (BYTE *) pwDelayPointer;

Mencampur Sampel Input dengan Sampel Penundaan

Di sinilah Anda menggunakan nilai campuran basah dan campuran kering untuk membuat sampel output akhir. Anda cukup mengalikan setiap sampel dengan nilai floating-point yang mewakili persentase sinyal akhir untuk sampel. Kalikan sampel input dengan nilai yang disimpan dalam m_fDryMix; kalikan sampel penundaan dengan nilai yang disimpan dalam m_fWetMix. Kemudian, tambahkan dua nilai. Kode yang harus Anda tambahkan identik untuk bagian 8-bit dan 16-bit:

// Mix the delay with the dry signal.
i = (int)((i * m_fDryMix ) + (delay * m_fWetMix));   

Menulis Data ke Buffer Output

Terakhir, salin sampel campuran ke buffer output, lalu lanjutkan penunjuk buffer output. Untuk audio 8-bit, wizard plug-in menggunakan kode berikut untuk mengembalikan sampel ke rentang aslinya:

// Convert back to 0..255 and write to output buffer.
*pbOutputData++ = (BYTE)(i + 128);

Untuk audio 16-bit, wizard menggunakan kode berikut sebagai langkah terakhir dalam perulangan pemrosesan:

// Write to output buffer.
*pwOutputData++ = i;

Menerapkan CEcho::D oProcessOutput