Creating Shazam in JavaA couple of days ago I encountered this article dịch - Creating Shazam in JavaA couple of days ago I encountered this article Việt làm thế nào để nói

Creating Shazam in JavaA couple of

Creating Shazam in Java

A couple of days ago I encountered this article: How Shazam Works

This got me interested in how a program like Shazam works… And more importantly, how hard is it to program something similar in Java?
About Shazam

Shazam is an application which you can use to analyse/match music. When you install it on your phone, and hold the microphone to some music for about 20 to 30 seconds, it will tell you which song it is.

When I first used it it gave me a magical feeling. “How did it do that!?”. And even today, after using it a lot, it still has a bit of magical feel to it.
Wouldn’t it be great if we can program something of our own that gives that same feeling? That was my goal for the past weekend.
Listen up..!

First things first, get the music sample to analyse we first need to listen to the microphone in our Java application…! This is something I hadn’t done yet in Java, so I had no idea how hard this was going to be.

But it turned out it was very easy:

final AudioFormat format = getFormat(); //Fill AudioFormat with the wanted settings
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
final TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();

Now we can read the data from the TargetDataLine just like a normal InputStream:

// In another thread I start:

OutputStream out = new ByteArrayOutputStream();
running = true;

try {
while (running) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-1);
}

Using this method it is easy to open the microphone and record all the sounds! The AudioFormat I’m currently using is:

private AudioFormat getFormat() {
float sampleRate = 44100;
int sampleSizeInBits = 8;
int channels = 1; //mono
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}

So, now we have the recorded data in a ByteArrayOutputStream, great! Step 1 complete.
Microphone data

The next challenge is analyzing the data, when I outputted the data I received in my byte array I got a long list of numbers, like this:

0
0
1
2
4
7
6
3
-1
-2
-4
-2
-5
-7
-8
(etc)

Erhm… yes? This is sound?

To see if the data could be visualized I took the output and placed it in Open Office to generate a line graph:

graph

Ah yes! This kind of looks like ‘sound’. It looks like what you see when using for example Windows Sound Recorder.

This data is actually known as time domain. But these numbers are currently basically useless to us… if you read the above article on how Shazam works you’ll read that they use a spectrum analysis instead of direct time domain data.
So the next big question is: How do we transform the current data into a spectrum analysis?
Discrete Fourier transform

To turn our data into usable data we need to apply the so called Discrete Fourier Transformation. This turns the data from time domain into frequency domain.
There is just one problem, if you transform the data into the frequency domain you loose every bit of information regarding time. So you’ll know what the magnitude of all the frequencies are, but you have no idea when they appear.

To solve this we need a sliding window. We take chunks of data (in my case 4096 bytes of data) and transform just this bit of information. Then we know the magnitude of all frequencies that occur during just these 4096 bytes.
Implementing this

Instead of worrying about the Fourier Transformation I googled a bit and found code for the so called FFT (Fast Fourier Transformation). I’m calling this code with the chunks:

byte audio[] = out.toByteArray();

final int totalSize = audio.length;

int amountPossible = totalSize/Harvester.CHUNK_SIZE;

//When turning into frequency domain we'll need complex numbers:
Complex[][] results = new Complex[amountPossible][];

//For all the chunks:
for(int times = 0;times < amountPossible; times++) {
Complex[] complex = new Complex[Harvester.CHUNK_SIZE];
for(int i = 0;i < Harvester.CHUNK_SIZE;i++) {
//Put the time domain data into a complex number with imaginary part as 0:
complex[i] = new Complex(audio[(times*Harvester.CHUNK_SIZE)+i], 0);
}
//Perform FFT analysis on the chunk:
results[times] = FFT.fft(complex);
}

//Done!

Now we have a double array containing all chunks as Complex[]. This array contains data about all frequencies. To visualize this data I decided to implement a full spectrum analyzer (just to make sure I got the math right).
To show the data I hacked this together:

for(int i = 0; i < results.length; i++) {
int freq = 1;
for(int line = 1; line < size; line++) {
// To get the magnitude of the sound at a given frequency slice
// get the abs() from the complex number.
0/5000
Từ: -
Sang: -
Kết quả (Việt) 1: [Sao chép]
Sao chép!
Tạo Shazam trong JavaMột vài ngày trước, tôi bắt gặp bài viết: làm thế nào các công trình ShazamĐiều này tôi đã quan tâm đến một chương trình như Shazam như thế... Và quan trọng hơn, làm thế nào cứng là nó để chương trình gì đó tương tự trong Java?Về ShazamShazam là ứng dụng mà bạn có thể sử dụng để phân tích/phù hợp với âm nhạc. Khi bạn cài đặt nó trên điện thoại của bạn, và giữ micro để một số âm nhạc trong khoảng 20 đến 30 giây, nó sẽ cho bạn biết bài hát đó là.Khi tôi lần đầu tiên sử dụng nó nó đã cho tôi một cảm giác kỳ diệu. "Làm thế nào đã làm nó làm điều đó?". Và thậm chí ngày nay, sau khi sử dụng nó rất nhiều, nó vẫn có một chút của huyền diệu để cảm thấy nó.Sẽ không thể tuyệt vời nếu chúng ta có thể chương trình gì đó của riêng của chúng tôi cung cấp cho cảm giác tương tự? Đó cũng là mục tiêu của tôi cho ngày cuối tuần qua.Nghe đây..!Điều đầu tiên đầu tiên, có được âm nhạc mẫu để phân tích chúng ta cần đầu tiên để nghe micro trong ứng dụng Java của chúng tôi...! Đây là một cái gì đó tôi đã không thực hiện được nêu ra trong Java, do đó, tôi không có ý tưởng làm thế nào cứng này sẽ.Nhưng nó bật ra rất dễ dàng:cuối cùng AudioFormat định dạng = getFormat(); Điền vào AudioFormat với những cài đặt mong muốnThông tin DataLine.Info = mới DataLine.Info (TargetDataLine.class, định dạng);cuối cùng TargetDataLine dòng = AudioSystem.getLine(info) (TargetDataLine);Line.Open(format);Line.Start();Bây giờ chúng ta có thể đọc dữ liệu từ TargetDataLine giống như InputStream bình thường:Trong chủ đề khác bắt đầu:OutputStream ra = mới ByteArrayOutputStream();chạy = true;cố gắng {} trong khi (chạy) {} số lượng int = line.read (đệm, 0, buffer.length); Nếu (số > 0) {} out.write (bộ đệm, 0, tính); } } out.Close();} bắt (IOException e) {} System.err.println ("I/O vấn đề:" + e); System.Exit(-1);}Bằng cách sử dụng phương pháp này là dễ dàng để mở micro và ghi lại tất cả các âm thanh! AudioFormat tôi hiện đang sử dụng là:tư nhân AudioFormat getFormat() {} float sampleRate = 44100; int sampleSizeInBits = 8; int kênh = 1; Mono boolean ký = true; boolean bigEndian = true; trở lại mới AudioFormat (sampleRate, sampleSizeInBits, kênh, ký kết, bigEndian);}Vì vậy, bây giờ chúng tôi có các dữ liệu được ghi nhận trong một ByteArrayOutputStream tuyệt vời! Bước 1 hoàn tất.Dữ liệu MicroThách thức tiếp theo phân tích dữ liệu, khi tôi outputted các dữ liệu mà tôi đã nhận được trong mảng byte của tôi tôi có một danh sách dài của các số như thế này:00124763-1-2-4-2-5-7-8(vv)Erhm... đúng không? Đây là âm thanh?Để xem nếu các dữ liệu có thể được hình dung tôi lấy đầu ra và đặt nó trong các văn phòng mở để tạo ra một đồ thị dòng:đồ thịAh yes! Điều này loại giống như 'âm thanh'. Nó trông giống như những gì bạn thấy khi sử dụng ví dụ Windows Sound Recorder.Dữ liệu này thực sự được biết đến như là tên miền thời gian. Nhưng những con số này hiện nay về cơ bản vô ích, để chúng ta... nếu bạn đọc các bài viết ở trên về Shazam như thế bạn sẽ đọc rằng họ sử dụng một phân tích quang phổ thay vì thời gian trực tiếp tên miền dữ liệu.Vì vậy, câu hỏi lớn tiếp theo là: làm thế nào chúng tôi làm biến đổi các dữ liệu hiện tại vào một phân tích quang phổ?Biến đổi Fourier rời rạcĐể chuyển dữ liệu của chúng tôi vào các dữ liệu có thể sử dụng chúng ta cần phải áp dụng biến đổi Fourier rời rạc như vậy gọi là. Điều này lần lượt các dữ liệu từ thời gian miền vào phạm vi tần số.Không chỉ là một vấn đề, nếu bạn chuyển dữ liệu vào phạm vi tần số bạn mất mỗi bit thông tin liên quan đến thời gian. Vì vậy, bạn sẽ biết những gì đang có tầm quan trọng của tất cả các tần số, nhưng bạn không có ý tưởng khi họ xuất hiện.Để giải quyết điều này, chúng ta cần một cửa sổ trượt. Chúng tôi mất khối dữ liệu (trong trường hợp của 4.096 byte dữ liệu) và biến đổi này chút thông tin. Sau đó, chúng tôi biết tầm quan trọng của tất cả các tần số xảy ra trong quá trình chỉ những 4.096 byte.Thực hiện điều nàyThay vì lo lắng về việc chuyển đổi Fourier tôi googled một chút và tìm thấy mã như vậy gọi là FFT (nhanh chóng biến đổi Fourier). Tôi gọi điện thoại bằng các khối mã này:âm thanh byte [] = out.toByteArray();cuối cùng int totalSize = audio.length;int amountPossible = totalSize/Harvester.CHUNK_SIZE;Khi quay vào phạm vi tần số, chúng tôi sẽ cần số phức:Khu phức hợp [] [] kết quả = mới phức tạp [amountPossible] [];Cho tất cả các khối:cho (int lần = 0; lần < amountPossible; lần ++) {} Khu phức hợp [] phức tạp = mới Complex[Harvester.CHUNK_SIZE]; cho (int i = 0; i < Harvester.CHUNK_SIZE;i++) {} Đưa dữ liệu tên miền thời gian vào một số phức với phần ảo là 0: khu phức hợp [i] = mới phức tạp (âm thanh [(times*Harvester.CHUNK_SIZE) + i], 0); } Thực hiện phân tích FFT trên đoạn: kết quả [thời gian] = FFT.fft(complex);}Đã hoàn tất!Bây giờ chúng tôi có một mảng đôi có chứa tất cả khối như phức tạp []. Mảng này chứa dữ liệu về tất cả các tần số. Để hình dung dữ liệu này, tôi quyết định thực hiện một phân tích đầy đủ (chỉ để đảm bảo rằng tôi đã tính toán đúng).Để hiển thị các dữ liệu tôi tấn công này với nhau:cho (int i = 0; i < results.length; i ++) {} int freq = 1; cho (int dòng = 1; dòng < kích thước; dòng ++) {} Để có được độ lớn của âm thanh tại một lát cho tần số nhận được abs() từ số phức.
đang được dịch, vui lòng đợi..
Kết quả (Việt) 2:[Sao chép]
Sao chép!
Tạo Shazam trong Java

Một vài ngày trước, tôi bắt gặp bài viết này: Làm thế nào Shazam Làm việc

này cũng làm tôi quan tâm đến việc làm thế nào một chương trình như Shazam hoạt động ... Và quan trọng hơn, làm thế nào cứng là nó để chương trình một cái gì đó tương tự như trong Java?
Về Shazam

Shazam là một ứng dụng mà bạn có thể sử dụng để phân tích / trận đấu âm nhạc. Khi bạn cài đặt nó trên điện thoại của bạn, và giữ microphone một số âm nhạc trong khoảng 20-30 giây, nó sẽ cho bạn biết bài hát nó được.

Khi tôi lần đầu tiên sử dụng nó nó đã cho tôi một cảm giác kỳ diệu. "Làm thế nào mà nó làm điều đó !?". Và ngay cả ngày hôm nay, sau khi sử dụng nó rất nhiều, nó vẫn có một chút cảm giác huyền diệu với nó.
Nó sẽ không thể tuyệt vời nếu chúng tôi có thể lập trình một cái gì đó của riêng của chúng tôi cung cấp cho cảm giác giống nhau không? Đó là mục tiêu của tôi cho ngày cuối tuần qua.
Nghe lên ..!

Trước tiên, có mẫu âm nhạc để phân tích đầu tiên chúng ta cần lắng nghe microphone trong ứng dụng Java của chúng tôi ...! Đây là điều tôi đã không thực hiện được nêu trong Java, vì vậy tôi không có ý tưởng như thế nào khó khăn này đã có được.

Nhưng hóa ra nó là rất dễ dàng:

định dạng AudioFormat thức = getFormat (); // Điền AudioFormat với các thiết lập truy nã
DataLine.Info info = mới DataLine.Info (TargetDataLine.class, định dạng);
thức dòng TargetDataLine = (TargetDataLine) AudioSystem.getLine (thông tin);
line.open (định dạng);
line.start ( );

Bây giờ chúng ta có thể đọc dữ liệu từ TargetDataLine giống như một InputStream bình thường:

// Trong thread khác tôi bắt đầu:

OutputStream ra = new ByteArrayOutputStream ();
chạy = true;

try {
while (chạy) {
int count = line.read (buffer, 0, buffer.length);
if (count> 0) {
out.write (buffer, 0, số);
}
}
out.close ();
} catch (IOException e) {
System.err.println ( " I / O vấn đề: "+ e);
System.exit (-1);
}

Sử dụng phương pháp này nó rất dễ dàng để mở micro và ghi lại tất cả các âm thanh! Các AudioFormat Tôi hiện đang sử dụng là:

tin AudioFormat getFormat () {
float sampleRate = 44100;
int sampleSizeInBits = 8;
int kênh = 1; // mono
boolean ký = true;
boolean bigEndian = true;
trở AudioFormat mới (sampleRate, sampleSizeInBits, kênh, ký kết, bigEndian);
}

Vì vậy, bây giờ chúng tôi có các dữ liệu được ghi lại trong một ByteArrayOutputStream, tuyệt vời! Bước 1 hoàn tất.
Dữ liệu Microphone

Thách thức tiếp theo là phân tích các dữ liệu, khi tôi xuất ra các dữ liệu tôi nhận được trong mảng byte của tôi, tôi có một danh sách dài những con số, như thế này:

0
0
1
2
4
7
6
3
-1
-2
-4
-2
-5
-7
-8
(vv)

Erhm ... đúng? Đây là âm thanh?

Để xem dữ liệu có thể được hình dung tôi đã lấy ra và đặt nó trong Open Office để tạo ra một biểu đồ đường:

đồ thị

Ah vâng! Kiểu này trông giống như 'âm thanh'. Dường như những gì bạn nhìn thấy khi sử dụng ví dụ Windows Sound Recorder.

Những thông tin này là thực sự được gọi là miền thời gian. Nhưng những con số này hiện nay về cơ bản là vô dụng đối với chúng ta ... nếu bạn đọc bài viết ở trên về cách Shazam hoạt động bạn sẽ đọc mà họ sử dụng một phân tích quang phổ thay vì dữ liệu miền thời gian trực tiếp.
Vì vậy, câu hỏi lớn tiếp theo là: Làm thế nào chúng ta chuyển đổi hiện nay dữ liệu vào một phân tích quang phổ?
Fourier rời rạc biến

để chuyển dữ liệu của chúng tôi vào dữ liệu có thể sử dụng chúng ta cần phải áp dụng cái gọi là rời rạc Fourier Transformation. Điều này lần lượt các dữ liệu từ miền thời gian sang miền tần số.
Chỉ có một vấn đề, ​​nếu bạn chuyển dữ liệu vào miền tần số bạn mất mỗi bit thông tin liên quan đến thời gian. Vì vậy, bạn sẽ biết những gì tầm quan trọng của tất cả các tần số đang có, nhưng bạn không có ý tưởng khi chúng xuất hiện.

Để giải quyết điều này chúng ta cần một cửa sổ trượt. Chúng tôi có khối dữ liệu (trong trường hợp của tôi 4096 byte dữ liệu) và chuyển đổi chỉ là chút thông tin này. Sau đó, chúng ta biết được độ lớn của tất cả các tần số xảy ra trong quá trình này tồn tại chỉ 4096 byte.
Thực hiện điều này

Thay vì lo lắng về việc chuyển đổi Fourier Tôi googled một chút và thấy mã cho FFT để gọi (Fast Fourier Transformation). Tôi gọi mã này với các khối:

byte âm thanh [] = out.toByteArray ();

thức int totalSize = audio.length;

int amountPossible = totalSize / Harvester.CHUNK_SIZE;

// Khi chuyển vào miền tần số, chúng tôi sẽ cần phải phức tạp số:
Complex [] [] kết quả = new Complex [amountPossible] [];

// đối với tất cả các khối:
for (int lần 0 =; lần <amountPossible; lần ++) {
Complex [] phức tạp = new Complex [Harvester.CHUNK_SIZE] ;
for (int i = 0; i <Harvester.CHUNK_SIZE; i ++) {
// Đặt các dữ liệu miền thời gian vào một số phức với phần ảo là 0:
phức tạp [i] = new Complex (audio [(lần * Harvester.CHUNK_SIZE ) + i], 0);
}
// Thực hiện phân tích FFT trên đoạn:
kết quả [lần] = FFT.fft (phức tạp);
}

// Xong!

Bây giờ chúng ta có một mảng hai có chứa tất cả các khối như Complex []. Mảng này chứa dữ liệu về tất cả các tần số. Để hình dung dữ liệu này, tôi quyết định thực hiện một phân tích quang phổ đầy đủ (chỉ để chắc chắn rằng tôi có các toán phải).
Để hiển thị các dữ liệu tôi bị hack này với nhau:

for (int i = 0; i <results.length; i ++) {
int freq = 1;
for (int dòng = 1; dòng <size; dòng ++) {
// để có được độ lớn của âm thanh ở một tần số nhất định lát
// có được abs () từ các số phức.
đang được dịch, vui lòng đợi..
 
Các ngôn ngữ khác
Hỗ trợ công cụ dịch thuật: Albania, Amharic, Anh, Armenia, Azerbaijan, Ba Lan, Ba Tư, Bantu, Basque, Belarus, Bengal, Bosnia, Bulgaria, Bồ Đào Nha, Catalan, Cebuano, Chichewa, Corsi, Creole (Haiti), Croatia, Do Thái, Estonia, Filipino, Frisia, Gael Scotland, Galicia, George, Gujarat, Hausa, Hawaii, Hindi, Hmong, Hungary, Hy Lạp, Hà Lan, Hà Lan (Nam Phi), Hàn, Iceland, Igbo, Ireland, Java, Kannada, Kazakh, Khmer, Kinyarwanda, Klingon, Kurd, Kyrgyz, Latinh, Latvia, Litva, Luxembourg, Lào, Macedonia, Malagasy, Malayalam, Malta, Maori, Marathi, Myanmar, Mã Lai, Mông Cổ, Na Uy, Nepal, Nga, Nhật, Odia (Oriya), Pashto, Pháp, Phát hiện ngôn ngữ, Phần Lan, Punjab, Quốc tế ngữ, Rumani, Samoa, Serbia, Sesotho, Shona, Sindhi, Sinhala, Slovak, Slovenia, Somali, Sunda, Swahili, Séc, Tajik, Tamil, Tatar, Telugu, Thái, Thổ Nhĩ Kỳ, Thụy Điển, Tiếng Indonesia, Tiếng Ý, Trung, Trung (Phồn thể), Turkmen, Tây Ban Nha, Ukraina, Urdu, Uyghur, Uzbek, Việt, Xứ Wales, Yiddish, Yoruba, Zulu, Đan Mạch, Đức, Ả Rập, dịch ngôn ngữ.

Copyright ©2025 I Love Translation. All reserved.

E-mail: