Soạn thảo 1 Nguyờn lý

Một phần của tài liệu Xây dựng chương trình xử lý âm thanh số (Trang 57 - 62)

4.1. Nguyờn lý

Trong phần này, ta thực hiện một số thao tỏc trực quan trờn màn hỡnh. Tức là thao tỏc qua sự hiển thị của dữ liệu gốc được biểu diễn theo thời gian. Ta chỉ ỏp dụng với dữ liệu gốc, tức là dữ liệu õm thanh chưa được xử lý (chưa qua cỏc quỏ trỡnh lọc hay được giới hạn qua hàm cưả sổ). Và cỏc phộp xử lý này chỉ tỏc động lờn một tệp õm thanh trong mỗi phiờn làm việc, cú nghĩa là mọi thao tỏc xử lý trờn phần súng õm của một tệp được hiển thị trờn màn hỡnh, sau đú nếu muốn lưu cỏc thay đổi thỡ cỏc tệp õm mới sẽ cú định dạng như tệp gốc. Chỳng sẽ cú cựng header với tần số lấy mẫu, số kờnh truyền, ... chỉ khỏc cỏc mẫu dữ liệu.

Nờn, nếu F là tham số tệp gốc, và Fsave là tham số của tệp õm mới được lưu sau một số thao tỏc soạn thảo, và header cú dạng WaveHeaderFile (trong chương trỡnh mới chỉ ỏp dụng soạn thảo trờn tệp Wave, tuy nhiờn muốn soạn thảo trờn khuụn dạng khỏc ta cú thể chuyển đổi khuụn dạng về dạng Wave, hay núi chung cơ sở của thuật toỏn trờn cỏc khuụn dạng khỏc cũng tương tự như vậy). Assigned(F, MainFilename); Assigned(Fsave, CurentFilename); Reset(F); Rewrite(Fsave); BlockRead(F, Header, 44);

{... Thay đổi tham số về độ dài dữ liệu ...} BlockWrite(Fsave, Header);

Close(F); Close(Fsave);

4.2. Thao tỏc dưới dạng trực quan

Thực chất của cỏc thao tỏc là tỏc động một cỏch trực quan lờn hai màn hỡnh: màn hỡnh biểu diễn súng õm gốc và màn hỡnh soạn thảo. Nếu cỏc thao tỏc chỉ đơn giản là cắt hay xoỏ bớt cỏc mẫu của dữ liệu gốc thỡ chỉ cần một màn hỡnh biểu diễn dữ liệu gốc là đủ. Bởi ta sẽ cắt, xoỏ ngay trờn phần súng õm gốc, và sau đú ghi phần súng õm cũn lại dưới dạng một tệp mới cú cựng định dạng kiểu.

Để cú thể chọn phần dữ liệu tỏc động, ta sử dụng phương phỏp nhấn và kộo chuột để khoanh vựng dữ liệu, hay chọn toàn bộ phần súng õm hiển thị.

Hỡnh 4.5: Chọn một phần dữ liệu

Theo cỏch nhỡn trực quan cũng như xột theo khớa cạnh về sự thay đổi của súng õm gốc, thỡ thay đổi do cỏc phộp cắt, xoỏ tạo ra là như nhau: phần dữ liệu lựa chọn bị xoỏ mất, và khi lưu tạo tệp mới thỡ cỏc mẫu dữ liệu phớa sau sẽ dồn lờn chiếm chỗ cỏc mẫu dữ liệu đó mất.

Hỡnh 4.6: Xoỏ phần dữ liệu đó chọn

Tuy nhiờn, những thay đổi đú chỉ cú thể làm thay đổi vị trớ chứ khụng phải trỡnh tự lưu trữ dữ liệu. Muốn cú một trỡnh tự mới, ta phải cắt, ghộp cỏc phần súng õm tương ứng tuỳ theo mong muốn. Chớnh vỡ vậy, ta cần một màn hỡnh thứ 2 (chớnh là màn hỡnh soạn thảo) để cú thể biểu diễn cỏc phõn đoạn súng õm theo một trỡnh tự nào đú.

Hỡnh 4.7: Màn hỡnh soạn thảo

Do đú, cú sự khỏc nhau giữa lệnh cắt và xoỏ. Lệnh cắt khỏc ở chỗ xoỏ phần súng trờn màn hỡnh nhưng lại lưu vào bộ nhớ đệm. Mặc dự ta cú thể lưu ảnh của phần súng õm, và như vậy khi lệnh dỏn được kớch hoạt ta sẽ dỏn ra màn hỡnh ảnh tương ứng, nhưng khi tạo một tệp dữ liệu ta phải xột tới cỏc mẫu dữ liệu, do đú phải lưu thụng tin về cỏc mẫu đó tỏc động.

4.3. Cơ chế thực hiện

Màn hỡnh súng õm gốc

Khởi tạo một mảng kiểu “boolean” (DelCut: array ...) cú kớch thước bằng kớch thước của mảng lưu trữ cỏc mẫu dữ liệu. Mỗi khi mở một tệp mới, mọi thành phần trong mảng được khởi tạo giỏ trị “true”.

Trờn màn hỡnh súng õm gốc, khi cú bất cứ thao tỏc cắt hay xoỏ nào xẩy ra (cú nghĩa là một số mẫu dữ liệu đó bị mất), ta sẽ đỏnh dấu vị trớ cỏc mẫu tương ứng bằng cỏch gỏn giỏ trị “false”:

Begin

for i:=StartPoint to FinitPoint do DelCut[i]:=false; CutDel:=true;

End;

Trong đú, StartPoint và FinitPoint là vị trớ mẫu bắt đầu và cuối cựng của phần bị xoỏ. Để cú thể tớnh được vị trớ cỏc mẫu tương ứng này, ta phải xỏc định toạ độ (theo toạ độ màn hỡnh) điểm bắt đầu và kết thỳc khi nhấn và kộo chuột khi muốn chọn một phần súng õm, sau đú quy ngược lại cỏc mẫu tớn hiệu cú vị trớ tương ứng.

Ngoài ra, sử dụng thờm biến kiểm tra trạng thỏi CutDel: false - khụng cú thay đổi nào với cỏc mẫu; true - đó cú thay đổi (một số mẫu đó bị xoỏ).

Sau đú, khi muốn ghi tệp õm đú sang một tệp mới ta sẽ chộp toàn bộ cỏc mẫu trong tệp gốc sang tệp mới, tức là cỏc mẫu trong khoảng từ mẫu thứ nhất, tới vị trớ mẫu liền trước vị trớ mẫu đầu tiờn được đọc ra; và cỏc mẫu từ vị trớ liền sau mẫu cuối cựng được đọc ra tới cuối tệp.

Seek(F,44);

For i:=1 to DebutPoint-1 do

{... sao chộp cỏc mẫu từ F sang Fsave ...};

và:

seek(F, 44+ (DebutPoint + NumSamples)*numBytesPerSample); While not eof(F) do

{... sao chộp dữ liệu từ F sang Fsave ...};

Nhưng sẽ kiểm tra riờng cỏc mẫu tớn hiệu tương ứng với phần súng õm trờn màn hỡnh qua biến DelCut[i]. Và phần súng õm này gồm NumSamples mẫu tớn hiệu liờn tiếp bắt đầu từ mẫu thứ DebutPoint trong tệp dữ liệu. (adsbygoogle = window.adsbygoogle || []).push({});

for i:= 1 to NumSamples do begin if DelCut[i] then begin seek(F,44+ (DebutPoint+i)*numBytesPerSample); {... read(F,temp);write(fSave,temp);...} end; end;

Trong đú, numBytesPerSample là số byte mà mỗi mẫu dữ liệu cần lưu trữ: 1- dạng dữ liệu PCM 8bits; 2- dạng dữ liệu PCM 16bits.

Ngoài ra, phần sao chộp cỏc mẫu giữa cỏc tệp phải lưu ý tới số kờnh truyền, 1: dạng mono và 2: dạng stereo, và dạng lưu trữ dữ liệu PCM, 8 hay 16 bits tức là số cỏc byte dựng để lưu trữ mỗi mẫu.

Hỡnh 4.8: Súng õm tệp gốc và của tệp sao chộp với một số mẫu đầu bị xoỏ

Ghi phần dữ liệu được lựa chọn

Ta cú thể chọn một phần dữ liệu trờn phần súng õm gốc để lưu dưới dạng một tệp riờng.

seek(F,44 + (DebutPoint + StartPoint)* numBytesPerSample); for i:= 1 to (FinitPoint-StartPoint+1)*numBytesPerSample do begin read(F,temp); write(fSave,temp); end; Hỡnh 4.9: Súng õm phần lựa chọn Màn hỡnh soạn thảo

Đõy là màn hỡnh ta dựng để hiển thị cỏc phõn đoạn súng õm được dỏn sau khi đó thực hiện lệnh sao chộp hay cắt. Mỗi lần dỏn, cỏc phõn đoạn sẽ được xếp kế tiếp nhau. Cho nờn, để đạt được theo một trỡnh tự mong muốn, ta sẽ sao chộp hay dỏn cỏc phõn đoạn mong muốn theo trỡnh tự đú. Hơn nữa, cỏc biến FinitPoint và StartPoint sẽ nhận giỏ trị tương ứng ngay sau cỏc phộp cắt hay sao

chộp xảy ra (như bộ nhớ đệm chỉ lưu duy nhất một giỏ trị). Nờn khi dỏn, thao tỏc sẽ xử lý với dữ liệu của phần lựa chọn sau cựng.

Và để lưu phần súng õm trờn màn hỡnh soạn thảo, ta sử dụng mảng PointEdit cú cựng kiểu với dữ liệu trong tệp õm (integer). Mỗi lần thực hiện thao tỏc dỏn, ta sẽ đọc cỏc mẫu tớn hiệu tương ứng từ tệp gốc và gỏn vào cỏc giỏ trị PointEdit[i].

seek(F,44+ (StartPoint + DebutPoint)*numBytesPerSample); for i:= 1 to (FinitPoint-StartPoint+1)*numBytesPerSample do begin

read(F,temp);

PointEdit[i + NumEdit] :=temp; end;

NumEdit:=NumEdit+(FinitPoint-StartPoint+ 1)*numBytesPerSample;

Trong đú, NumEdit là một biến kiểu nguyờn và nhận giỏ trị là số mẫu hiện thời cú trong mảng PointEdit. Khi mở một tệp mới hay khi bắt đầu một phiờn cắt ghộp cỏc phõn đoạn súng mới, biến NumEdit sẽ nhận giỏ trị khởi đầu là 0.

Khi thao tỏc ghi phần soạn thảo được kớch hoạt, sau phần header cựng định dạng ta sẽ gỏn toàn bộ cỏc giỏ trị trong mảng PointEdit vào cỏc bytes liờn tiếp trong tệp mới với cựng trỡnh tự.

Hỡnh 4.10: Súng õm của tệp được cắt ghộp từ một số phõn đoạn

Một phần của tài liệu Xây dựng chương trình xử lý âm thanh số (Trang 57 - 62)