SpiroComp : Spirometer Digital Menggunakan Microphone Laptop Casmika Saputra 10212001 Program Studi Fisika Institut Teknologi Bandung
[email protected] Abstrak. Telah dibuat SpiroComp, yaitu spirometer yang memanfaatkan microphone laptop sebagai sensor ekspirasi. Dilakukan signal processing dengan cara pendeteksian Hilbert Envelope hingga konversi menjadi parameter fungsi paru. Parameter tersebut adalah FVC, FEV1, Rasio FEV1/FVC, dan PEF. Kemudian ditampilkan dalam bentuk grafik Volume-Flow dan Volume-Waktu dapat digenerate dari sinyal audio ekspirasi. Namun, penelitian ini belum dapat dipakai untuk diagnosa kedokteran. Karena hasil penelitian belum dilakukan kalibrasi dan pembandingan dengan menggunakan spirometer standar. Kata kunci : SpiroComp, Spirometer, FEV1, FVC, dan PEF
PENDAHULUAN Salah satu instrumentasi medis untuk menganalisis fungsional paru-paru adalah spirometer. Spirometer sudah banyak dikembangkan mulai dari model konvensional hingga beralih ke digital. Secara konvensionala spirometer dapat dibuat menggunakan selang dan tabung penampung udara serta menggunakan pena untuk membuat kurva volume atau flow rate terhadap waktu [1]. Digital spirometer menggunakan sensor flow rate. Biasanya menggunakan selang yang dihubungkan dengan sensor flow rate dan seperangkat perangkat instrumentasi. Inovasi terbaru spirometer adalah menggunakan microphone HP sebagai sensor flow rate nya. Seperti yang dikembangkan oleh Eric C. Larson dkk, Spirosmart. Spirosmart menggunakan microphone HP untuk mengukur fungsi paru-paru. Namun, aplikasi spirosmart hanya dapat digunakan menggunakan HP tertentu yang memenuhi spesifikasi. Pada penelitian ini, ide spirosmart digunakan untuk membuat spirometer menggunakan microphone pada Laptop, disebut SpiroComp.
METODE Pengukuran pada dasarnya “merekam” respon setelah sistem diberi gangguan. Pada beberapa pengukuran, sistem tidak diberi gangguan, melainkan dari karakteristik sistem tersebutlah yang dipakai pada pengukuran, SpiroComp menggunakan metode ini.
Gambar 1. Pendeteksian Sistem
Responden (Sampel) berekspirasi maksimal dan kemudian sensor (microphone) mendeteksi gelombang suara (audio) yang diahsilkan saat berekspirasi maksimal. Gelombang suara yang ditangkap kemudian diproses untuk menghasilkan grafik Volume ekspirasi terhadap waktu dan volume ekspirasi terhadap flow rate (Debit).
Gambar 2. Skema Signal Processing
Buffer berperan sebagai penyimpan sementara sinyal audio sebelum di proses. Sinyal yang direkam memiliki 44100 frame per detik (44100 datum setiap detiknya). Gambar 3 berikut merupakan sampel yang telah direkam.
Gambar 3. Sinyal audio ekspirasi
Amplitudo sinyal audio yang terbentuk telah ternormalisasi, sehingga memberikan nilai amplitudo maksimum sebesar 1. Dari gambar 3 terlihat jelas sinyal audio ekpirasi terbentuk pada sekira t = 2 s hingga t = 3 s. Untuk selang t < 2 s dan t > 3 s masih terbentuk sinyal dengan amplitudo yang sangat kecil. Sinyal tersebut tidak diinginkan, sehingga dianggap sebagai nois. Untuk menganalisisnya maka dilakukan FFT (Fast Fourrier TransformI) untuk menentukan spektrumnya. Berikut hasil FFT sinyal audio t = 0 s hingga t = 2 s.
Gambar 4. Sinyal Nois
Gambar 5. sinyal audio ekspirasi
Filter digunakan untuk menghilangkan / meredam nois. Terlihat jelas, sinyal nois memiliki spektrum yang lebar. Sedangkan untuk sinyal audio ekspirasi hanya dominan pada frekuensi rendah, sehingga untuk menghilangkan nois maka sinyal harus di filter dengan hanya meloloskan frekuensi rendah. Dipilih Low Pass Filter dengan frekuensi cut-off sebesar 200 Hz. Selain itu nilai ini dipilih sehingga mencegah suara dengan audiosonik (20Hz – 20kHz) manusia tidak berdampak pada pengukuran. Filter digital menggunakan butterwood ordo 6 dengan frekuensi cut of 200Hz.
Gambar 6. Spektrum sinyal audio ekspirasi setelah difilter. Untuk memudahkan pengolahan, sinyal masukan dikonversi sehingga menjadi 100 frame per detik.
Gambar 7. Sebelum (kiri) dan sesudah (kanan) konnversi 44100 fps menjadi 100 fps
Hibert Transform digunakan untuk membuat Hilbert Envelope yang kemudian digunakan untuk mendeteksi sinyal ekspirasi. Sinyal ekspirasi memiliki karakterisiti tertentu sehingga dalam rekaman sinyal dapat dideteksi (Deteksi Hilbert Envelope) dan kemudian dipotong. Hasil potongan tersebutlah yang akan digunakan dan diproses lebih lanjut. Pendeteksian Hilbert Envelope dapat dilakukan dengan membandingkan karakteristik sinyal dengan karakteristik sinyal referensi. Sinyal referensi digenerate menggunakan fungsi berikut: (1) y ( t )=1.5t exp (−2 t 2) Untuk mendeteksi sinyal dengan karakteristik ekspirasi, digunakan fungsi pada persamaan 1 sebagai pembanding. Iterasi dilakukan dari t = 0 s hingga t maksimum sinyal sampel. Apa bila ditemukan absolut simpangan sinyal yang
memiliki pola mirip dengan persamaan 1 maka sinyal tersebut lah yang dianggap sebagai sinyal ekspirasi sedangkan sinyal lainnya diabaikan. Berikut adalah contoh sinyal ekspirasi yang dideteksi melalui Hilbert Envelope.
Gambar 8. Sinyal referensi (kiri) dan sinyal audio ekspirasi yang dideteksi (kanan)
Smoothing dan Aproksimasi, pada bagian ini hasil kurva yang dideteksi diperhalus dengan metode rata-rata. Nilai rata-rata dilkukan untuk menentukan nilai y i+1 dengan mengambil nilai rata-rata y i dan y i +2 . Perhitungan iterasi dilakukan dengan persamaan berikut:
y i+1=
y i + y i +2 2
(2)
Gambar 9. Sinya audio ekspirasi yang sudah di smoothing
Sinyal audio (suara) dapat ditinjau sebagai gelombang tekanan. Perubahan tekanan yang merambat di medum udara menimbulkan getaran pada microphone sehingga suara terdeteksi. Simpangan tekanan berupa sinyal audio y(t) secara empiris akan sebanding dengan kuadrat debit hembusan udara (flow rate) dari mulut [1]. v (t )=k √ y (t) atau secara numerik v i=k √ y i (3)
Dengan v(t) debit (flow rate) sebagai fungsi waktu, y(t) merupakan sinyal audio ekspirasi yang dideteksi, dan k merupakan konstanta kesebandingan yang dapat dikalibrasi melaluli percobaan. Volume gas ekspirasi dapat dihitung dengan cara mengintegralkan flow rate terhadap waktu. Dan dapat dihitung melalui persamaan berikut: t
t
V (t )=∫0 v (t )dt=k ∫0 √ y ( t)dt atau secara numerik V i =∑ v i Δ t
(4)
Gambar 10. hasil aproksimasi volume dengan k = 4410.35
Penentuan konstanta k melalui kalibrasi (akan dibahas pada subbab selanjutnya). Hasil nilai fitur volume-time memperlihatkan adanya waktu mulai bukan pada t = 0. Perhitungan zero time (waktu mulai) sebagai perhitungan tidak boleh sembarangan. Waktu mulai didefinisikan seperti gambar berikut [2]:
Gambar 11. Zero Time
dengan menggunakan metode Back Extrapolation maka nilai zero time dapat ditentukan dengan mudah. Setelah zero time diketahui maka fitur Volume-time dengan koreksi zero time serta fitur Flow-Volume dapat dibuat dengan mudah.
Gambar 12. fitur flow-volume (kiri) dan fitur Volume-time (kanan)
Kalibrasi dilakukan dengan cara eksperimen. Ekspirasi maksimum dihembuskan kedalam plastik kemudian dilakukan pengukuran volume udara pada plasti tersebut. Dengan hembusan ekspirasi dilakukan dengan SpiroComp. Dengan cara ini, konstanta k pada persamaan 4 dapat ditentukan.
k=
V eksperimen
(5)
t
∫0 √ y (t) dt
konstanta k hasil kalibrasi ini kemudian digunakan untuk pengukuran fungsional paru-paru menggunakan SpiroComp. Grafik User Interface pada SpiroComp menggunakan Proccessing. Processing merupakan free open source software. Processing programing berbasis Java. Interface dibuat menggunakan Processing, namun pengolahan data menggunakan software Octave. Octave merupakan free software yang memiliki fungsi dan struktur programingnya sama persis dengan MatLab. Begitupun file exitensinya berupa .m dan dapat dikompile. SpiroComp dibuat berbasis Linux.
HASIL DAN DISKUSI Kalibrasi SpiroComp Kalibrasi dilakukan menggunakan percobaan untuk menentukan volume ekspirasi berdasarkan percobaan dan menggunakan SpiroComp. Berdasarkan percobaan dengan menggunakan plastik penampung ekspirasi dan dilakukan pengukuran volumenya serta menggunakan SpiroComp empat kali pengukuran, diperoleh nilai k hasil pengukuran pertama dan seterusnya berturut-turut 4741.1, 4205.0, 3958.6, 4760.7. Nilai k rata-rata = 4416.35. nilai k ini dipakai dalam uji SpiroComp pada beberapa responden (sampel).
Grafik User Interface SpiroComp
Gambar 13. Tampilan muka SpiroComp
Gambar 14. Tampilan SpiroComp – Result
Hasill pengukuran ditampilkan grafik flow-volume dan volume-time dan disertai dengan nilai parameter fungsional paru-paru, FVC (mL), FEV1 (mL), PEV (mL/s), dan rasio FEV1/FVC (%).
Pengaruh Kondisi Lingkungan Pengukuran SpiroComp menggunakan sinyal audio ekspirasi, sinyal audio dapat dipengaruhi kondisi lingkungan. Tentu, pengukuran yang baik adalah dilakukan pada suasana lingkungan senyap (tidak berisik). Namun, hal tersebut umumnya sulit dipenuhi. Sehingga, diuji SpiroComp dengan kondisi lingkunang relatif bising. Suasana bising dibuat dengan memutar musik saat dilakukan pengukuran. Dilakukan pengukuran dengan nois musik Metal, Pop, dan Dangdut dan diperoleh hasil berikut:
Gambar 15. Nois musik Pop
Gambar 16. Nois musik Rock
Gambar 17. Nois musik Dangdut
Gambar 18. Kondisi Senyap
Terlihat pada gambar 15 hingga 17, grafik flow-volume mengalami sedikit riak (gejolak) akibat adanya sinyal audio tambahan dari musik. Terutama pada musik rock dan pop, riak (gejolak naik-turun) pada grafik lebih terlihat jelas. Berbeda dengan kondisi yang relatif senyap, kurvanya cenderung lebih mulus dibanding yang lain. Pada grafik volume-time tidak terlalu berdampak. Pengamatan menunjukan nois tidak terlalu berdampak pada perhitungan volume. Ini disebabkan Signal per Nois (S/N) nya besar. Nois musik ini sangat mempengaruhi FEV1 dan FVC sehingg nilai rasio FEV1/FVC pun memberikan nilai berbeda. Terlihat pada gambar 15 – 17, nilai rasio FEV1/FVC praktis menjadi < 80 %, sedangkan pada kondisi senyap, nilainya menjadi > 80%.
Pengaruh Jarak Mulut – Microphone Perambatan sinyal audio dalam medium udara akan mengalami ipedansi, sehingga sinyal akan melemah seiring jarak mulut – microphone bertambah. Untuk mengetahui pengaruh ini, SpiroComp diuji dengan memvariasikan jarak mulut – microphone dan diperoleh data sebagai berikut: Tabel 1. Variasi jarak mulut – microphone (d) FEV1 (mL) FVC (mL) PEF (mL/s) FEV1/FVC (%) 1539.74 2228.87 2346.05 69.08 1747.59 2213.95 2535.84 78.94 1578.01 1895.93 2467.42 83.23 1584.13 1922.95 2509.09 82.38 1252.83 1448.01 2066.93 86.52 1026.50 1205.98 1626.95 85.12 763.23 941.45 1398.86 81.07 808.16 1085.37 1437.17 74.46 580.41 804.97 960.67 72.10 626.11 928.69 941.04 67.42 396.08 726.74 814.11 54.50
d (cm) 1 2 5 10 15 20 25 30 35 40 45
Sedangkan grafik volume-time dan flow-volume terlampir. Karakteristik grafik volume-time dan flow-volume memberikan bentuk kurva yang sama untuk setiap variasi jarak. Namun, nilai parameter-parameter fungsional paru-paru bergantung pada jarak. Grafik 1. Variasi jarak 3000 2500 2000 FEV1 (mL) FVC (mL) PEF (mL/s)
1500 1000 500 0 0
5
10
15
20
25
30
35
40
45
50
d (cm)
Grafik 1 menjelaskan bahwa semakin besar jarak mulut-microphone nilai yang terukur semakin melemah. Namun, terlalu dekat pun memberikan nilai yang kurang stabil. Grafik 2. Rasio FEV1/FVC terhadap jarak mulut – microphone
FEV1/FVC (%)
100 90 80 70 60 50 40 30 20 10 0 0
5
10
15
20
25
30
35
40
45
50
d (cm)
Grafik 2 menunjukan bahwa nilai rasio FEV1/FVC relatif stabil untuk d berbeda-beda. Hasi ini memberikan informasi bahwa pengukuran dapat dilakukan pada rentang tertentu dimana pengukuran memberikan nilai optimum. Nilai optimum diperoleh pada d = 5 cm hingga d = 10 cm. Namun, untuk pengukuran rasio tanpa memperhatikan nilai FEV1 maupun FVC nya dapat dilakukan pada rentang d = 5 cm hingga d = 25 cm. SOP SpiroComp Pengukuran SpiroComp memberikan hasil yang bergantung pada pengambilan datanya. Sehingga dibuat Standar Operational Prosedure (SOP) dalam melakukan pengukuran menggunakan SpiroComp. 1. Posisi Mulut dan Microphone Laptom tidak terlalu dekan dan terlalu jauh (5 – 10) cm 2. Posisi tuhuh sebisamungkin tegap 3. Nyalakan SpiroComp untuk merekam sample ekspirasi 4. Inspirasi smaksimal mungkin, kemudian ekspirasi semaksimal mungkin didepan microphon Laptop. (hembusan ekspirasi diarahkan ke microphone laptop) 5. Semua tahap harus mengikuti instruksi dari Istruktur Uji SpiroComp Hasil uji SpiroComp diliakukan kepada beberapa responden yang telah diketahui kondisi (riwayat) kesehatan responden. Namun, uji belum dilakukan diagnosis dari dokter. Berikut ini hasil uji SpiroComp pada beberapa Responden. Tabel 2. Uji SpiroComp Responden Andi Kuswoyo Anita Aziz AF Azka MB Casmika Saputra Dwi Susilo Erna
umur (tahun) 21 19 20 23 20 19 19
jenis klamin FVC (mL) FEV1 (mL) PEF (mL/s) FEV1/FVC (%) Riwayat Laki-laki 3398.75 2821.48 4913.28 83.02 Sehat Perempuan 3850.04 2924.06 4058.45 75.95 Sehat Laki-laki 3308.6 2344.28 4715.47 70.85 Sehat Laki-laki 2314.87 1691.7 3129.5 73.08 Sehat Laki-laki 1991.16 1635.81 2429.76 82.15 Sehat Perempuan 2410.14 2046.66 5127.12 84.92 Sehat Perempuan 2295.6 1503.97 2450.27 65.52 Riwayat Asma
Untuk kondisi sehat (paru-paru sehat) nilai FEV1/FVC > 80 %. Pada uji SpiroComp diperoleh 3 responden sehat FEV1/FVC > 80 % dan 3 responden sehat FEV1/FVC
> 70 %. Berdasarkan referensi, fungsional paru-paru normal FEV1/FVC > 80%. Haslil uji, menunjukkan keberhasilan diagnosis FEV1/FVC normal hingga 50%. sedangkan untuk responden dengan riwayat asma memiliki FEV1/FVC = 65.52%. Hasil ini menunjukan fungsional paru-paru lebih lemah dibanding orang normal (sehat). Namun, semua hasil hanya didiagnosis dan analisis oleh penulis, sehingga untuk uji SpiroComp harus dilakukan peninjauan lebih lanjut dengan cara membandingkannya dengan hasil menggunakan spirometer standar kedokteran serta rujukan diagnosa Dokter.
KESIMPULAN SpiroComp telah dibuat menggunakan microphone laptop sebagai sensor flow rate untuk untuk pengukuran fungsional paru-paru. Hasil uji SpiroComp mampu mengukur FEV1/FVC secara tepat dengan keberhasilan 50%. Grafik Volume-Flow dan Volume-Waktu dapat digenerate dari sinyal audio ekspirasi maksimal responden. SpiroComp-Result dapat di save dan dijadikan sebagai pemantauan dini kondisi paru-paru.
REFERENSI [1] Larson, Eric C., dkk. SpiroSmart: Using a Microphone to Measure Lung Function on a Mobile Phone. [2] Stewart, R.I, E. Basson. Standardisationofspirometry. SAMJ VOL79 6APR1991 [3] S. Ananthi. Medical Instruments. New Age International.
DAFTAR SIMBOL
v (t ) : flow rate (debit) dalam mL/s V (t ) : Volume dalam mL
y (t) : simpangan gelombang tekanan (gelombang suara) v i : besar flow rate ke-i V i : besar volume ke-i y i : simpangan gelombang ke-i k : Konstanta kalibrasi Fps : Frame per Second
LAMPIRAN Hasil Uji Responden
SCRIPT PROGRAM 1. Script Octave disave dalam file spiro.m clear; clc; clf; filename = "myrecording.wav"; [WaveSource,Fs] = wavread(filename); Buf(1:4*Fs) = 0; if length(WaveSource) < 3*Fs +10; for i = 1:length(WaveSource) - 1; Buf(i) = WaveSource(i); endfor Wave = Buf; endif if length(WaveSource) > 3*Fs + 9; Wave = WaveSource; endif [b,a] = butter(6,200/Fs); Wave = filter(b,a, Wave); t = 0:1/Fs:(length(Wave)-1)/Fs; %Hilbert Transform Wave = hilbert(Wave); %Convert wave Fs to fs L = length(Wave); fs = 100; indexMax = fs*L/Fs; wave(1:indexMax) = 0; for j = 1:indexMax; tempMax = 0; for i = (j-1)*Fs/fs +1 : j*Fs/fs; if abs(tempMax) < abs(Wave(i)); tempMax = Wave(i); endif wave(j) = tempMax; endfor endfor %Create Envelope Function for detecting Hilbert Envelope waveHilbert(1:2*fs) = 0; tH = 0 : 1/fs : 1.99; for i = 1:2*fs; x = i/fs; waveHilbert(i) = 1.5*x*exp(-2* x^2 ); endfor
% Hilbert Env elope env = abs(wave); start = -1; % Detected Hilbert Envelope kriteria = 2; while start < 0; for j = floor(indexMax) - 2*fs : -1 : 1; detec = 0; for i = 2*fs:-1:1; if env(j+i - 1) > waveHilbert(i); detec ++ ; endif endfor if detec > kriteria*fs; start = j; endif endfor kriteria -= 0.1; endwhile if start == -1; Detected = false endif % LPC if start != -1; %Create detected Hilbert Envelope waveDetected(1:3*fs) = 0; tH = 0 : 1/fs : 2.99; for i = 1:3*fs; waveDetected(i) = wave(start+i); endfor % Aproximate wave absWave = abs(waveDetected); for j = 1:10; for i = 1:3*fs-2; absWave(i+1) = (absWave(i) +absWave(i+2))/2; endfor endfor % u(t) ~ sqrt(2p(t)) % Kflow with experiment Kflow = 4416.35; absWave = absWave -min(absWave(1:3*fs - 4)); flow = Kflow * sqrt(2*absWave); for z = 1:2*fs; if flow(z) == max(flow);
pfs = z; endif endfor dt = 1/fs; Volume(1:3*fs) = 0; tempVolume = 0; for i = 1:3*fs; Volume(i) = tempVolume + flow(i)*dt; tempVolume = Volume(i); endfor Vsaturasi = max(Volume); grad = (Volume(pfs) - Volume(pfs - 5))/5; to = pfs - Volume(pfs)/grad; to = floor(to) - 10; if to > 100; to = 100; endif tempFlow = flow; for i = 1:2*fs ; tempFlow(i) = flow(i+to); endfor flow = tempFlow; % Integrating to Volume % Volume = flow.t tempVolume = 0; tSaturasi = 0; for i = 1:2*fs; Volume(i) = tempVolume + flow(i)*dt; tempVolume = Volume(i); %FEV1 if i == fs; FEV1 = tempVolume; endif if Volume(i)/Vsaturasi > 0.9 && tSaturasi == 0; tSaturasi = i; endif endfor FVC = max(abs(Volume)); PEF = max(flow); FEV1 = abs(FEV1); Ratio = FEV1/FVC; t_Sat = tSaturasi; figure(1); h = figure; plot(Volume(1:2*fs-4), flow(1:2*fs-4), 'LineWidth', 4); title('Volume vs Flow', 'FontSize', 20, 'FontWeight', 'bold');
ylabel('Flow (mL/s)', 'FontSize', 20, 'FontWeight', 'bold'); xlabel('Volume (mL)', 'FontSize', 20, 'FontWeight', 'bold'); set(gca, 'FontSize', 15, 'FontWeight', 'bold'); saveas(h, 'result1', 'png'); figure(2); plot(tH(1:2*fs-4), Volume(1:2*fs-4), 'LineWidth', 4); title('Time vs Volume', 'FontSize', 20, 'FontWeight', 'bold'); ylabel('Volume (mL)', 'FontSize', 20, 'FontWeight', 'bold'); xlabel('t (Seconds)', 'FontSize', 20, 'FontWeight', 'bold'); set(gca, 'FontSize', 15, 'FontWeight', 'bold'); saveas(h, 'result2', 'png'); save('RESULT.txt','FVC','PEF', 'FEV1', 'Ratio', 't_Sat','-ascii'); endif
2. SCRIPT C++ Untuk mengkompile file spiro.m secara otomatis maka dibuat aplikasi menggunakan C++ untuk mengkompile spiro.m secara otomatis. Disave dengan nama file : run.cpp #include
#include <stdlib.h> using namespace std; int main() { system("octave spiro.m"); } kemudian dikompile dengan cara g++ run.cpp -o run 3. SCRIPT PROCESSING Scrip Processing terdiri dari 6 file script dengan ekxitensi .pde file utama, diberi nama SpiroComp.pde import ddf.minim.*; Minim minim; AudioInput in; AudioRecorder recorder; PImage logo, graf1, graf2, CekGraph; boolean indHome = true; boolean klik = false; void setup() { size(1000, 600); logo = loadImage("logo.jpg"); recSetup(); open("/home/cms/Documents/simulasi cpp/FFT/spiro/SpiroComp/reset"); } void draw() { home(); record(); load(); result(); klik = false; } void mouseReleased() { klik = true; }
file kedua : Home.pde String name = ""; String age = ""; String sex = ""; boolean indName = true; boolean indAge = false; boolean indSex = false; void home() { if(indHome) { background(0); textSize(77); fill(255); text("SpiroComp", 300, 100); image(logo, 50, 185); stroke(255); fill(0); rect(550,200, 100, 50); rect(670,200, 280, 50); rect(550,270, 100, 50); rect(670,270, 280, 50); rect(550,340, 100, 50); rect(670,340, 280, 50); rect(710,410, 200, 50); fill(255); textSize(25); if(mouseX > 670 && mouseY > 200 && mouseX < 950 && mouseY < 250 && klik) { indName = true; indAge = false; indSex = false; } if(mouseX > 670 && mouseY > 270 && mouseX < 950 && mouseY < 320 && klik) { indName = false; indAge = true; indSex = false; } if(mouseX > 670 && mouseY > 340 && mouseX < 950 && mouseY < 390 && klik) { indName = false; indAge = false; indSex = true; } if((millis()/500)%2 == 0 && indName) { text("Name " + name + "|", 565,235); } else { text("Name " + name, 565,235); } if((millis()/500)%2 == 0 && indAge) { text("Age " + age + "|", 575,305); } else { text("Age " + age, 575,305);
} if((millis()/500)%2 == 0 && indSex) { text("Sex " + sex + "|", 575,375); } else { text("Sex " + sex, 575,375); } if(mouseX > 710 && mouseY > 410 && mouseX < 910 && mouseY < 460) { fill(255); rect(715, 415, 190, 40); fill(0); text("Test...", 775,450); if(klik) { if(name != "" && age != "" && sex != "") // Go to Slide 2 indHome = false; inisialRec = true; Records = true; } } } text("Test...", 775,450); } }
{
file ketiga : Loading.pde boolean proccess = false; boolean loading = false; int timeLoad; void load() { if(proccess) { open("/home/cms/Documents/simulasi cpp/FFT/spiro/SpiroComp/run"); proccess = false; } if(loading) { background(0); textSize(50); fill(255); lines = loadStrings("RESULT.txt"); if(lines.length != 5) { text("Proccessing....", 300,400); println(lines.length); } else { proccess = false; loading = false; setupResult(); indResult = true; } } }
File keempat : Record.pde boolean indRec; boolean indClc; boolean indSave; boolean indFinisRec; boolean indR; boolean indC; boolean indS; boolean Records = false; boolean inisialRec = false; void recSetup() { minim = new Minim(this); in = minim.getLineIn(); } void record() { if(inisialRec) { indRec = false; indClc = false; indSave = false; indFinisRec = false; indR = false; indC = false; indS = false; recorder = minim.createRecorder(in, "myrecording.wav"); inisialRec = false; } if(Records) { background(0); stroke(255); textSize(77); fill(255); text("SpiroComp", 300, 100); image(logo, 50, 25, 150,100); stroke(255); textSize(30); text("Name : " + name, 50, 200); text("Age : " + age, 50, 230); text("Sex : " + sex, 55, 260); fill(0); rect(50,300,900,200); for (int i = 50; i < 950; i++) { line(i, 400 + in.left.get(i)*100, i+1, 400 + in.left.get(i+1)*100); } rect(760,200,50,50); rect(830,200,50,50); rect(900,200,50,50); rect(75, 525, 100,50); rect(825, 525, 100,50); fill(255); text(" R", 755, 235); text(" C", 825, 235); text(" S", 900, 235);
text(" Back", 75, 565); text(" Next", 825, 565); if((mouseX > 760 && mouseY > 200 && mouseX < 810 && mouseY < 250 || indR) && !indFinisRec) { fill(255); rect(760,200,50,50); fill(0); text(" R", 755, 235); if(klik) { indR = true; indC = false; indS = false; indRec = true; indClc = false; indSave = false; } } if(mouseX > 830 && mouseY > 200 && mouseX < 880 && mouseY < 250 || indC) { fill(255); rect(830,200,50,50); fill(0); text(" C", 825, 235); if(klik) { indC = true; indR = false; indS = false; indRec = false; indClc = true; indSave = false; } } if(mouseX > 900 && mouseY > 200 && mouseX < 950 && mouseY < 250 || indS) { fill(255); rect(900,200,50,50); fill(0); text(" S", 900, 235); if(klik) { indS = true; indR = false; indC = false; indRec = false; indClc = false; indSave = true; } } if(indRec && !indFinisRec) { recorder.beginRecord(); status = "Currently recording..."; indRec = false; } if(indClc) {
recorder.endRecord(); recorder.save(); recorder = minim.createRecorder(in, "myrecording.wav"); status = "Not recording !"; indClc = false; indFinisRec = false; } if(indSave) { recorder.save(); status = "Done Saving !"; indSave = false; indFinisRec = true; } if(mouseX > 75 && mouseY > 525 && mouseX < 175 && mouseY < 570) { fill(255); rect(75, 525, 100,50); fill(0); text(" Back", 75, 565); if(klik) { Records = false; indHome = true; } } if(mouseX > 825 && mouseY > 525 && mouseX < 925 && mouseY < 570) { fill(255); rect(825, 525, 100,50); fill(0); text(" Next", 825, 565); if(klik) { Records = false; // Goto Slide 3 proccess = true; loading = true; } } fill(255); text(status, 400, 550); } }
File kelima : Result.pde
boolean indResult = false; boolean statusSave = false; float[] param = new float[5]; float FVC, PEF, FEV, Ratio, Tsat; String[] lines; void setupResult() { graf1 = loadImage("result1.png"); graf2 = loadImage("result2.png"); lines = loadStrings("RESULT.txt"); for(int index = 0; index < lines.length; index++) { param[index] = float(lines[index]); } FVC = param[0]; PEF = param[1]; FEV = param[2]; Ratio = param[3]; Tsat = param[4]; } void result() { if(indResult) { background(255); stroke(0); textSize(40); fill(0); text("SpiroComp - Result", 300, 50); stroke(0); textSize(14); line(25,75, 975, 75); line(25,150, 975, 150); text("Name : " + name, 50, 100); text("Age : " + age, 50, 120); text("Sex : " + sex, 50, 140); text("FVC : " + String.format("%.2f", FVC) + " mL", 550, 110); text("FEV1 : " + String.format("%.2f", FEV) + " mL", 550, 130); text("PEV : " + String.format("%.2f", PEF) + " mL/s", 700, 110); text("FEV1/FVC : " + String.format("%.2f", Ratio*100) + " %", 700, 130); text("Test-date : " + day() + "/" + month() + "/" + year(), 800,25); rect(24,199,452,377); rect(524,199,452,377); image(graf1, 25, 200, 450, 375); image(graf2, 525, 200, 450, 375); fill(200); rect(20,15,50,50); rect(80,15,50,50); if(mouseX > 20 && mouseY > 15 && mouseX < 70 && mouseY < 65) { fill(100); rect(20,15,50,50); if(klik) { open("/home/cms/Documents/simulasi cpp/FFT/spiro/SpiroComp/reset");
statusSave = false; indResult = false; indHome = true; } } if(mouseX > 80 && mouseY > 15 && mouseX < 130 && mouseY < 65) { fill(100); rect(80,15,50,50); if(klik) { String save = "output/" + name + ".png"; saveFrame(save); statusSave = true; } } fill(0); textSize(20); text("New Save", 25,50); if(statusSave) { text("Done Saving !", 140, 30); } } }
File keenam : keyPressed.pde int charCountName = 0; int charCountAge = 0; int charCountSex = 0; int countName = 0; int countAge = 0; int countSex = 0; char[] charsName = new char[50]; char[] charsAge = new char[20]; char[] charsSex = new char[20]; String status = " "; void keyReleased() { if ((key == 'r' || key == 'R' ) && Records && !indFinisRec ) { indR = true; indC = false; indS = false; indRec = true; indClc = false; indSave = false; } if ((key == 'c' || key == 'C') && Records ) { indC = true; indR = false; indS = false; indRec = false; indClc = true; indSave = false; } if ((key == 's' || key == 'S') && Records ) { indS = true; indR = false; indC = false; indRec = false; indClc = false; indSave = true; } if(indName && ((key >= '!' && key <= 'z') || key == ' ' || key == 8)) { if(key != 8) { if(charCountName < 15) { charsName[charCountName] = key; name = name + key; charCountName ++; } } else { String tempName = ""; charCountName --; if(charCountName < 0) { charCountName = 0; } for(int i = 0; i < charCountName; i++) { tempName = tempName + charsName[i];
} for(int i = charCountName; i < charsName.length; i++ ) { charsName[i] = 0; } name = tempName; } } if(indAge && ((key >= '!' && key <= 'z') || key == ' ' || key == 8)) { if(key != 8) { charsAge[charCountAge] = key; age = age + key; charCountAge ++; } else { String tempAge = ""; charCountAge --; if(charCountAge < 0) { charCountAge = 0; } for(int i = 0; i < charCountAge; i++) { tempAge = tempAge + charsAge[i]; } for(int i = charCountAge; i < charsAge.length; i++ ) { charsAge[i] = 0; } age = tempAge; } } if(indSex && ((key >= '!' && key <= 'z') || key == ' ' || key == 8)) { if(key != 8) { charsSex[charCountSex] = key; sex = sex + key; charCountSex ++; } else { String tempSex = ""; charCountSex --; if(charCountSex < 0) { charCountSex = 0; } for(int i = 0; i < charCountSex; i++) { tempSex = tempSex + charsSex[i]; } for(int i = charCountSex; i < charsSex.length; i++ ) { charsSex[i] = 0; } sex = tempSex; } } }