├── README.md ├── VoiceFilter.ipynb ├── assets ├── audio_samples │ ├── sample_1 │ │ ├── clean_1.flac │ │ ├── noise_1.flac │ │ └── target_1.flac │ └── sample_2 │ │ ├── clean_2.flac │ │ ├── noise_2.flac │ │ └── target_2.flac └── images │ ├── app.png │ ├── dev_sdr.png │ ├── loss.png │ ├── model_plot.png │ ├── model_workflow.PNG │ └── system_arch.PNG ├── configuration ├── Audio.py └── HyperParams.py ├── dataset ├── dataset_creation.py ├── directory_structure.py ├── preload_training_dataset.py └── speech_collection.py ├── flutter app └── voicefilter │ ├── .gitignore │ ├── README.md │ ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── voicefilter │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle │ ├── assets │ ├── audio1.png │ ├── audio2.png │ └── audio3.png │ ├── fonts │ ├── Montserrat-Regular.ttf │ ├── Poppins-Regular.ttf │ ├── Raleway-Regular.ttf │ └── Spartan-Regular.ttf │ ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h │ ├── lib │ ├── main.dart │ ├── screens │ │ ├── embedding_screen.dart │ │ ├── filter_screen.dart │ │ └── login_register_screen.dart │ ├── services │ │ ├── api.dart │ │ ├── auth_manager.dart │ │ └── auth_service.dart │ ├── utilities │ │ └── constants.dart │ └── widgets │ │ ├── custom_painter.dart │ │ ├── dialogbox.dart │ │ └── player_widget.dart │ ├── pubspec.yaml │ └── test │ └── widget_test.dart ├── model ├── model.py └── sequence_generator.py ├── requirements.txt └── train_test ├── testing.py └── train.py /README.md: -------------------------------------------------------------------------------- 1 | # Voice Filter 2 | 3 | This is a Tensorflow/Keras implementation of Google AI VoiceFilter. 4 | 5 | Our work is inspired from the the academic paper : https://arxiv.org/abs/1810.04826 6 | 7 | The implementation is based on the work : https://github.com/mindslab-ai/voicefilter 8 | 9 | --- 10 | 11 | ### Team Members 12 | 13 | 1. [Angshuman Saikia](https://github.com/HeliosX7) 14 | 15 | 1. [Abhinav Jain](https://github.com/jain-abhinav02) 16 | 17 | 1. [Yashwardhan Gautam](https://github.com/yashwardhan-gautam) 18 | 19 | --- 20 | 21 | ### Introduction 22 | We intend to improve the accuracy of Automatic speech recognition(ASR) by separating the speech of the primary speaker. 23 | This project has immense application in chatbots, voice assistants, video conferencing. 24 | 25 | --- 26 | 27 | ### Who is our primary speaker ? 28 | All users of a service will have to record their voice print during enrolment. The voice print associated with the account is used to identify the primary speaker. 29 | 30 | ### How is voice print recorded ? 31 | A audio clip is processed by a separately trained deep neural network to generate a speaker discriminative embedding. As a result, all speakers are represented by a vector of length 256. 32 | 33 | --- 34 | 35 | ### How to prepare Dataset ? 36 | We use the publicly available speech dataset - Librispeech. We select a primary and secondary speaker at random. For the primary speaker, select a random speech for reference and a random speech for input. Select a random speech of the secondary speaker. The input speeches of primary and secondary users are mixed which serves as one of the input. The reference speech is passed through a pre trained model ( Source: https://github.com/mindslab-ai/voicefilter ) to create an embedding which serves as the other input. The output is the input speech of the primary speaker. 37 | The speeches are not used directly. Instead, they are converted into magnitude spectrogram before being fed into a deep neural network. We have used python's librosa library to perform all audio related functions. 38 | 39 | We created a dataset of 29351 samples that have been divided into 8 parts for ease of use with limited RAM. 40 | Link to the kaggle dataset: https://www.kaggle.com/abhinavjain02/speech-separation 41 | 42 | --- 43 | 44 | ### Stats on Prepared Data 45 | 46 | It took around 11 hours to prepare the dataset on Google Colab. The code is present in the [dataset](/dataset) folder. 47 | 48 | > Note: All ordered pairs of primary and secondary speakers are unique 49 | 50 | | Stat/Dataset | Train | Dev | Test | 51 | |:----------------------------:|:-------------:|:-------------:|:----------:| 52 | | Total no. of unique speeches available in LibriSpeech Dataset | 28539 | 2703 | 2620 | 53 | | No. of unique speeches used | 26869 | 1878 | 1838 | 54 | | Percentage of total speeches used | 94.15 % | 69.48 % | 70.15 % | 55 | | Total no. of samples prepared | 29351 | 934 | 964 | 56 | | No. of samples with same primary and reference speech | 376 (1.28 %) | 10 (1.07 %) | 11 (1.14 %) | 57 | 58 | --- 59 | 60 | ### Proposed System Architecture 61 | 62 | 63 | 64 | --- 65 | 66 | ### Requirements 67 | 68 | * This code was tested on Python 3.6.9 with [Google Colab](colab.research.google.com). 69 | 70 | Other packages can be installed by: 71 | 72 | ``` 73 | pip install -r requirements.txt 74 | ``` 75 | 76 | 77 | ### Model 78 | 79 | 80 | 81 | --- 82 | 83 | The model architecture is precisely as per the academic paper mentioned above. The model takes a input spectrogram and d vector(embedding) as input and produces a soft mask which when superimposed on the input spectrogram produces the output spectrogram. The output spectrogram is combined with the input phase to re create the primary speakers audio from the mixed input speech. 84 | 85 | 86 | | Loss Function | Optimizer | Metrics | 87 | |:--------------------:|:------------------:|:-------------:| 88 | | Mean Squared Error (MSE) | adam | Sound to Distortion Ratio(SDR) | 89 | 90 | --- 91 | 92 | 93 | 94 | --- 95 | 96 | ### Training 97 | 98 | * The model was trained on Google Colab for 30 epochs. 99 | * Training took about 37 hours on NVIDIA Tesla P100 GPU. 100 | 101 | ### Results 102 | 103 | * Loss 104 | 105 | 106 | 107 | * Validation SDR 108 | 109 | 110 | 111 | * Test 112 | 113 | > Note: The following results are based on model weights after 29th epoch( Peak SDR on validation ) 114 | 115 | | Loss | SDR | 116 | |:-------------:|:------------:| 117 | | 0.0104 | 5.3250 | 118 | 119 | --- 120 | 121 | ### Audio Samples 122 | 123 | * Listen to the sample audio from the [assets/audio_samples](/assets/audio_samples) folder. 124 | 125 | --- 126 | 127 | ### Key learnings: 128 | 129 | * Processing Audio data using [librosa](https://github.com/librosa/librosa) 130 | * Creating flexible architechtures using [Keras functional API](https://keras.io/guides/functional_api/) 131 | * Using custom generator in keras 132 | * Using custom callbacks in keras 133 | * Multi-Processing in python 134 | 135 | --- 136 | 137 | ### App Snippet 138 | 139 | 140 | -------------------------------------------------------------------------------- /assets/audio_samples/sample_1/clean_1.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_1/clean_1.flac -------------------------------------------------------------------------------- /assets/audio_samples/sample_1/noise_1.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_1/noise_1.flac -------------------------------------------------------------------------------- /assets/audio_samples/sample_1/target_1.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_1/target_1.flac -------------------------------------------------------------------------------- /assets/audio_samples/sample_2/clean_2.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_2/clean_2.flac -------------------------------------------------------------------------------- /assets/audio_samples/sample_2/noise_2.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_2/noise_2.flac -------------------------------------------------------------------------------- /assets/audio_samples/sample_2/target_2.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_2/target_2.flac -------------------------------------------------------------------------------- /assets/images/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/app.png -------------------------------------------------------------------------------- /assets/images/dev_sdr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/dev_sdr.png -------------------------------------------------------------------------------- /assets/images/loss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/loss.png -------------------------------------------------------------------------------- /assets/images/model_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/model_plot.png -------------------------------------------------------------------------------- /assets/images/model_workflow.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/model_workflow.PNG -------------------------------------------------------------------------------- /assets/images/system_arch.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/system_arch.PNG -------------------------------------------------------------------------------- /configuration/Audio.py: -------------------------------------------------------------------------------- 1 | import librosa 2 | import numpy as np 3 | 4 | class Audio: 5 | def __init__(self,hyper_params): 6 | self.hyper_params = hyper_params 7 | self.mel_basis_matrix = librosa.filters.mel(sr=hyper_params.sample_rate, 8 | n_fft=hyper_params.n_fft, 9 | n_mels=hyper_params.embedder_num_mels) 10 | 11 | def get_mel_spec(self,wave): 12 | spec = librosa.core.stft(y=wave, n_fft=self.hyper_params.n_fft, 13 | hop_length=self.hyper_params.hop_length, 14 | win_length=self.hyper_params.win_length, 15 | window='hann') 16 | power_spec = np.abs(spec) ** 2 17 | mel_spec = np.log10(np.dot(self.mel_basis_matrix,power_spec)+1e-6) 18 | return mel_spec 19 | def wave2spec(self,wave): 20 | spec = librosa.core.stft(y=wave, n_fft=self.hyper_params.n_fft, 21 | hop_length=self.hyper_params.hop_length, 22 | win_length=self.hyper_params.win_length) 23 | phase = np.angle(spec) 24 | spec_db = self.amp2db(np.abs(spec)) 25 | spec_db_norm = self.normalize(spec_db) 26 | spec_db_norm = spec_db_norm.T # Taking transpose here 27 | phase = phase.T # Taking transpose here 28 | return spec_db_norm, phase 29 | def spec2wave(self,spec_db_norm,phase): 30 | spec_db_norm, phase = spec_db_norm.T, phase.T 31 | spec_db = self.denormalize(spec_db_norm) 32 | spec_amp = self.db2amp(spec_db) 33 | spec = spec_amp * np.exp(1j*phase) 34 | wave = librosa.core.istft(spec, 35 | hop_length=self.hyper_params.hop_length, 36 | win_length=self.hyper_params.win_length) 37 | return wave 38 | def amp2db(self,mat): 39 | return 20.0 * np.log10(np.maximum(1e-5,mat)) - self.hyper_params.ref_level_db 40 | def db2amp(self,mat): 41 | return np.power(10.0, (mat+self.hyper_params.ref_level_db)*0.05) 42 | def normalize(self,mat): 43 | return np.clip((mat-self.hyper_params.min_level_db)/-self.hyper_params.min_level_db, 0.0 , 1.0) 44 | def denormalize(self, mat): 45 | return np.clip(mat,0.0,1.0)*(-self.hyper_params.min_level_db)+self.hyper_params.min_level_db -------------------------------------------------------------------------------- /configuration/HyperParams.py: -------------------------------------------------------------------------------- 1 | class HyperParams: 2 | n_fft= 1200 3 | num_freq= 601 # n_fft//2 + 1 4 | sample_rate= 16000 5 | hop_length= 160 6 | win_length= 400 7 | min_level_db= -100.0 8 | ref_level_db= 20.0 9 | preemphasis= 0.97 10 | power= 0.30 11 | embedder_window= 80 12 | data_audio_len= 3.0 13 | embedder_num_mels= 40 14 | embedder_lstm_hidden = 768 15 | embedder_emb_dim = 256 16 | embedder_lstm_layers = 3 17 | embedder_window = 80 18 | embedder_stride = 40 19 | model_lstm_dim = 400 20 | model_fc1_dim = 600 21 | model_fc2_dim = 601 # num_freq -------------------------------------------------------------------------------- /dataset/dataset_creation.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import torch 4 | import torch.nn as nn 5 | import random 6 | import pandas as pd 7 | import time 8 | import numpy as np 9 | import librosa 10 | from multiprocessing import Pool 11 | from Audio import Audio 12 | from HyperParams import HyperParams 13 | 14 | class LinearNorm(nn.Module): 15 | def __init__(self, hp): 16 | super(LinearNorm, self).__init__() 17 | self.linear_layer = nn.Linear(hp.embedder_lstm_hidden, hp.embedder_emb_dim) 18 | 19 | def forward(self, x): 20 | return self.linear_layer(x) 21 | 22 | class SpeechEmbedder(nn.Module): 23 | def __init__(self, hp): 24 | super(SpeechEmbedder, self).__init__() 25 | self.lstm = nn.LSTM(hp.embedder_num_mels, 26 | hp.embedder_lstm_hidden, 27 | num_layers=hp.embedder_lstm_layers, 28 | batch_first=True) 29 | self.proj = LinearNorm(hp) 30 | self.hp = hp 31 | 32 | def forward(self, mel): 33 | # (num_mels, T) 34 | mels = mel.unfold(1, self.hp.embedder_window, self.hp.embedder_stride) # (num_mels, T', window) 35 | mels = mels.permute(1, 2, 0) # (T', window, num_mels) 36 | x, _ = self.lstm(mels) # (T', window, lstm_hidden) 37 | x = x[:, -1, :] # (T', lstm_hidden), use last frame only 38 | x = self.proj(x) # (T', emb_dim) 39 | x = x / torch.norm(x, p=2, dim=1, keepdim=True) # (T', emb_dim) 40 | x = x.sum(0) / x.size(0) # (emb_dim), average pooling over time frames 41 | return x 42 | 43 | def get_dvector(wave): 44 | mel_spec = audio.get_mel_spec(wave) 45 | dvec = embedder(torch.from_numpy(mel_spec).float()) 46 | dvec = dvec.detach().numpy() 47 | return dvec 48 | 49 | def create_example(target_dir, hyper_params, idx, ref_speech, pri_speech, sec_speech): 50 | sample_rate = hyper_params.sample_rate 51 | ref_wave, _ = librosa.load(ref_speech,sr=sample_rate) #load the audio file 52 | pri_wave, _ = librosa.load(pri_speech, sr = sample_rate) 53 | sec_wave,_ = librosa.load(sec_speech, sr = sample_rate) 54 | assert len(ref_wave.shape)==len(pri_wave.shape)==len(sec_wave.shape)==1,\ 55 | 'wave files must be mono and not stereo' 56 | ref_wave,_ = librosa.effects.trim(ref_wave, top_db = 20) # clip silent portion on both ends 57 | pri_wave,_ = librosa.effects.trim(pri_wave, top_db = 20) 58 | sec_wave,_ = librosa.effects.trim(sec_wave, top_db = 20) 59 | 60 | if ref_wave.shape[0] < 1.1 * hyper_params.embedder_window * hyper_params.hop_length : 61 | return 62 | length_wave = int(sample_rate * hyper_params.data_audio_len) 63 | if pri_wave.shape[0] 0: 105 | diff_mod = n1 - diff_mod 106 | ref_speech = speeches[first-1][diff_mod] 107 | pri_speech = speeches[first-1][sum%n1] 108 | sec_speech = speeches[sec-1][first%n2] 109 | row = create_example( path[dataset], hyper_params , n*(i-1) + j, ref_speech, pri_speech, sec_speech) 110 | if row is not None: 111 | batch.append(row) 112 | print(i) 113 | return batch 114 | 115 | def save_batch(dataset,data): 116 | df_path = os.path.join(path[dataset],'data_frame.csv') 117 | df = pd.read_csv(df_path) 118 | df_batch = pd.DataFrame(data = data, columns = columns) 119 | df = df.append(df_batch) 120 | df.to_csv(df_path,index=False) 121 | 122 | columns=['key','ref_speech','pri_speech','sec_speech','input_spec_path','output_spec_path','input_phase_path','output_phase_path','dvector_path'] 123 | hyper_params = HyperParams() 124 | audio = Audio(hyper_params) 125 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset') 126 | path = {} 127 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset') 128 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset') 129 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset') 130 | 131 | with open(os.path.join(path['dev'],'dev_speeches.data'),'rb') as f: 132 | dev_speeches = pickle.load(f) 133 | with open(os.path.join(path['test'],'test_speeches.data'),'rb') as f: 134 | test_speeches = pickle.load(f) 135 | with open(os.path.join(path['train'],'train_speeches.data'),'rb') as f: 136 | train_speeches = pickle.load(f) 137 | 138 | embedder_path = os.path.join(dataset_path,"embedder.pt") 139 | embedder_pt = torch.load(embedder_path,map_location=torch.device('cpu')) 140 | embedder = SpeechEmbedder(hyper_params) 141 | embedder.load_state_dict(embedder_pt) 142 | embedder.eval() 143 | 144 | cpu_num = len(os.sched_getaffinity(0)) 145 | 146 | #### Dev Dataset #### 147 | dataset = 'dev' # important global variable 148 | speeches = dev_speeches # important global variable 149 | n = len(dev_speeches) # important global variable 150 | print("number of speakers(dev set) : ",n) 151 | for i in range(n): 152 | random.shuffle(dev_speeches[i]) # shuffle the speeches of all speakers 153 | arr = list(range(1,n+1)) # create a list for all speakers 154 | 155 | data = [] 156 | parity = 0 # important global variable 157 | with Pool(cpu_num) as p: 158 | res = p.map(create_dataset, arr , 4) 159 | for batch in res: 160 | if len(batch) > 0: 161 | data.extend(batch) 162 | save_batch('dev',data) 163 | 164 | data = [] 165 | parity = 1 # important global variable 166 | with Pool(cpu_num) as p: 167 | res = p.map(create_dataset, arr , 4) 168 | for batch in res: 169 | if len(batch) > 0: 170 | data.extend(batch) 171 | save_batch('dev',data) 172 | 173 | #### Test dataset #### 174 | dataset = 'test' # important global variable 175 | speeches = test_speeches # important global variable 176 | n = len(test_speeches) # important global variable 177 | print("number of speakers(test set) : ",n) 178 | for i in range(n): 179 | random.shuffle(test_speeches[i]) # shuffle the speeches of all speakers 180 | arr = list(range(1,n+1)) # create a list for all speakers 181 | 182 | data = [] 183 | parity = 0 # important global variable 184 | x = time.time() 185 | with Pool(cpu_num) as p: 186 | res = p.map(create_dataset, arr , 4) 187 | for batch in res: 188 | if len(batch) > 0: 189 | data.extend(batch) 190 | y = time.time() 191 | print(y-x) 192 | save_batch('test',data) 193 | 194 | data = [] 195 | parity = 1 # important global variable 196 | x = time.time() 197 | with Pool(cpu_num) as p: 198 | res = p.map(create_dataset, arr , 4) 199 | for batch in res: 200 | if len(batch) > 0: 201 | data.extend(batch) 202 | y = time.time() 203 | print(y-x) 204 | save_batch('test',data) 205 | 206 | #### Train dataset #### 207 | dataset = 'train' # important global variable 208 | speeches = train_speeches # important global variable 209 | n = len(train_speeches) # important global variable 210 | print("number of speakers(train set) : ",n) 211 | for i in range(n): 212 | random.shuffle(train_speeches[i]) # shuffle the speeches of all speakers 213 | arr = list(range(1,n+1)) # create a list for all speakers 214 | 215 | data = [] 216 | parity = 0 # important global variable 217 | with Pool(cpu_num) as p: 218 | res = p.map(create_dataset, arr , 4) 219 | for batch in res: 220 | if len(batch) > 0: 221 | data.extend(batch) 222 | save_batch('train',data) 223 | 224 | ### Run the following code only to create additional 30k samples for training set 225 | #data = [] 226 | #parity = 1 # important global variable 227 | #with Pool(cpu_num) as p: 228 | # res = p.map(create_dataset, arr , 4) 229 | #for batch in res: 230 | # if len(batch) > 0: 231 | # data.extend(batch) 232 | #save_batch('train',data) 233 | 234 | 235 | -------------------------------------------------------------------------------- /dataset/directory_structure.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | import shutil 4 | 5 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset') 6 | path = {} 7 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset') 8 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset') 9 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset') 10 | 11 | shutil.unpack_archive(os.path.join(dataset_path,'dev-clean.tar.gz'),os.path.join(dataset_path)) 12 | # Rename the extracted folder LibriSpeech to LibriSpeech Dev Dataset 13 | shutil.unpack_archive(os.path.join(dataset_path,'test-clean.tar.gz'),os.path.join(dataset_path)) 14 | # Rename the extracted folder LibriSpeech to LibriSpeech Test Dataset 15 | shutil.unpack_archive(os.path.join(dataset_path,'train-clean-100.tar.gz'),os.path.join(dataset_path)) 16 | # Rename the extracted folder LibriSpeech to LibriSpeech Train Dataset 17 | 18 | for dataset in ('dev','test'): 19 | os.makedirs(os.path.join(path[dataset],'input_spec'),exist_ok=True) 20 | os.makedirs(os.path.join(path[dataset],'output_spec'),exist_ok=True) 21 | os.makedirs(os.path.join(path[dataset],'input_phase'),exist_ok=True) 22 | os.makedirs(os.path.join(path[dataset],'output_phase'),exist_ok=True) 23 | os.makedirs(os.path.join(path[dataset],'dvector'),exist_ok=True) 24 | 25 | def create_folders(i): 26 | os.makedirs(os.path.join(path['train'],'input_spec_'+i),exist_ok=True) 27 | os.makedirs(os.path.join(path['train'],'output_spec_'+i),exist_ok=True) 28 | os.makedirs(os.path.join(path['train'],'input_phase_'+i),exist_ok=True) 29 | os.makedirs(os.path.join(path['train'],'output_phase_'+i),exist_ok=True) 30 | os.makedirs(os.path.join(path['train'],'dvector_'+i),exist_ok=True) 31 | 32 | for i in range(8): 33 | create_folders(str(i)) 34 | 35 | columns=['key','ref_speech','pri_speech','sec_speech','input_spec_path','output_spec_path','input_phase_path','output_phase_path','dvector_path'] 36 | sample_data_frame = pd.DataFrame(data = [], columns=columns) 37 | for dataset in ('train','dev','test'): 38 | sample_data_frame.to_csv(os.path.join(path[dataset],'data_frame.csv'),index=False) -------------------------------------------------------------------------------- /dataset/preload_training_dataset.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | import numpy as np 4 | 5 | def load_col_data(data_frame ,indices, start_pos, end_pos, col): 6 | col_list = [] 7 | for i in range(start_pos,end_pos): 8 | idx = indices[i] 9 | col_list.append(np.load(data_frame[col][idx])) 10 | return np.array(col_list) 11 | 12 | def preload_training_data(cur_fraction, start_pos, end_pos): 13 | input_spec = load_col_data(df_train, list(range(num_samples)) , start_pos , end_pos ,'input_spec_path' ) 14 | np.save(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(cur_fraction),'input_spec'),input_spec) 15 | output_spec = load_col_data(df_train, list(range(num_samples)), start_pos, end_pos, 'output_spec_path') 16 | np.save(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(cur_fraction),'output_spec'), output_spec) 17 | dvec = load_col_data(df_train, list(range(num_samples)), start_pos, end_pos, 'dvector_path') 18 | np.save(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(cur_fraction),'dvec'),dvec) 19 | 20 | def load_all_data(dataset): 21 | output_spec = load_col_data(df, list(range(df.shape[0])), 0 , df.shape[0] ,'output_spec_path') 22 | output_phase = load_col_data(df,list(range(df.shape[0])), 0 , df.shape[0] ,'output_phase_path') 23 | input_spec = load_col_data(df, list(range(df.shape[0])), 0 , df.shape[0] ,'input_spec_path') 24 | input_phase = load_col_data(df,list(range(df.shape[0])), 0 , df.shape[0] ,'input_phase_path') 25 | dvec = load_col_data(df,list(range(df.shape[0])), 0 , df.shape[0] ,'dvector_path') 26 | np.save(os.path.join(path[dataset],'output_spec.npy'),output_spec) 27 | np.save(os.path.join(path[dataset],'output_phase.npy'),output_phase) 28 | np.save(os.path.join(path[dataset],'input_spec.npy'),input_spec) 29 | np.save(os.path.join(path[dataset],'input_phase.npy'),input_phase) 30 | np.save(os.path.join(path[dataset],'dvec.npy'),dvec) 31 | 32 | dataset_train = 'train' 33 | df_train = pd.read_csv(os.path.join(path[dataset_train],'data_frame.csv')) 34 | num_samples = df_train.shape[0] 35 | 36 | num_fractions = 8 37 | fraction_sizes = num_fractions * [ num_samples//num_fractions ] 38 | for i in range(num_samples%num_fractions): 39 | fraction_sizes[i]+=1 40 | print(fraction_sizes) 41 | 42 | start_pos = 0 43 | for i in range(num_fractions): 44 | end_pos = start_pos + fraction_sizes[i] 45 | preload_training_data(i,start_pos, end_pos) 46 | start_pos = end_pos 47 | 48 | load_all_data('dev') 49 | load_all_data('test') 50 | -------------------------------------------------------------------------------- /dataset/speech_collection.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import pickle 3 | import os 4 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset') 5 | path = {} 6 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset') 7 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset') 8 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset') 9 | 10 | #### Run this cell only the first time #### 11 | dev_base_path = os.path.join(path['dev'],'dev-clean') 12 | test_base_path = os.path.join(path['test'],'test-clean') 13 | train_base_path = os.path.join(path['train'],'train-clean-100') 14 | 15 | #### Run this cell only the first time #### 16 | dev_spks = os.listdir(dev_base_path) 17 | # list of all speaker folders 18 | dev_speeches = [glob.glob(os.path.join(dev_base_path,spk,'*','*.flac'),recursive=True) for spk in dev_spks] 19 | dev_speeches = [speeches for speeches in dev_speeches if len(speeches)>=2] 20 | # list of lists containing speeches of a speaker 21 | test_spks = os.listdir(test_base_path) 22 | # list of all speaker folders 23 | test_speeches = [glob.glob(os.path.join(test_base_path,spk,'*','*.flac'),recursive=True) for spk in test_spks] 24 | test_speeches = [speeches for speeches in test_speeches if len(speeches)>=2] 25 | # list of lists containing speeches of a speaker 26 | train_spks = os.listdir(train_base_path) 27 | # list of all speaker folders 28 | train_speeches = [glob.glob(os.path.join(train_base_path,spk,'*','*.flac'),recursive=True) for spk in train_spks] 29 | train_speeches = [speeches for speeches in train_speeches if len(speeches)>=2] 30 | # list of lists containing speeches of a speaker 31 | 32 | ##### Run this cell only the first time ##### 33 | with open(os.path.join(path['dev'],'dev_speeches.data'),'wb') as f: 34 | pickle.dump(dev_speeches,f) 35 | with open(os.path.join(path['test'],'test_speeches.data'),'wb') as f: 36 | pickle.dump(test_speeches,f) 37 | with open(os.path.join(path['train'],'train_speeches.data'),'wb') as f: 38 | pickle.dump(train_speeches,f) 39 | 40 | -------------------------------------------------------------------------------- /flutter app/voicefilter/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Exceptions to above rules. 43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 44 | -------------------------------------------------------------------------------- /flutter app/voicefilter/README.md: -------------------------------------------------------------------------------- 1 | # Voice Filter App 2 | 3 | A sample user-end app for the voicefilter implementation. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | 18 | ## App Snippet 19 | 20 | 21 | 22 | ## Instructions 23 | 24 | * Add Firebase to your app 25 | 26 | https://firebase.google.com/docs/flutter/setup 27 | 28 | 29 | * Deploy the voicefilter model in the parent directory using [Flask]() to any hosting service like [Heroku](www.heroku.com 30 | ), [GCP](cloud.google.com 31 | ), [AWS](aws.amazon.com 32 | ) and so on. Then add your API KEY in `services/api.dart` 33 | 34 | ``` 35 | String postUrl = "< API KEY >"; 36 | ``` 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.voicefilter" 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | multiDexEnabled true 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | } 65 | 66 | apply plugin: 'com.google.gms.google-services' 67 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 15 | 22 | 26 | 30 | 35 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/kotlin/com/example/voicefilter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.voicefilter 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.gms:google-services:4.3.3' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /flutter app/voicefilter/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /flutter app/voicefilter/assets/audio1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/assets/audio1.png -------------------------------------------------------------------------------- /flutter app/voicefilter/assets/audio2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/assets/audio2.png -------------------------------------------------------------------------------- /flutter app/voicefilter/assets/audio3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/assets/audio3.png -------------------------------------------------------------------------------- /flutter app/voicefilter/fonts/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /flutter app/voicefilter/fonts/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Poppins-Regular.ttf -------------------------------------------------------------------------------- /flutter app/voicefilter/fonts/Raleway-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Raleway-Regular.ttf -------------------------------------------------------------------------------- /flutter app/voicefilter/fonts/Spartan-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Spartan-Regular.ttf -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 97C146F11CF9000F007C117D /* Supporting Files */, 94 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 95 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 96 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 97 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 98 | ); 99 | path = Runner; 100 | sourceTree = ""; 101 | }; 102 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | /* End PBXGroup section */ 110 | 111 | /* Begin PBXNativeTarget section */ 112 | 97C146ED1CF9000F007C117D /* Runner */ = { 113 | isa = PBXNativeTarget; 114 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 115 | buildPhases = ( 116 | 9740EEB61CF901F6004384FC /* Run Script */, 117 | 97C146EA1CF9000F007C117D /* Sources */, 118 | 97C146EB1CF9000F007C117D /* Frameworks */, 119 | 97C146EC1CF9000F007C117D /* Resources */, 120 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 121 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = Runner; 128 | productName = Runner; 129 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 97C146E61CF9000F007C117D /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 1020; 139 | ORGANIZATIONNAME = ""; 140 | TargetAttributes = { 141 | 97C146ED1CF9000F007C117D = { 142 | CreatedOnToolsVersion = 7.3.1; 143 | LastSwiftMigration = 1100; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 148 | compatibilityVersion = "Xcode 9.3"; 149 | developmentRegion = en; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | Base, 154 | ); 155 | mainGroup = 97C146E51CF9000F007C117D; 156 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 97C146ED1CF9000F007C117D /* Runner */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 97C146EC1CF9000F007C117D /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 171 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 172 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 173 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXResourcesBuildPhase section */ 178 | 179 | /* Begin PBXShellScriptBuildPhase section */ 180 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 181 | isa = PBXShellScriptBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | ); 185 | inputPaths = ( 186 | ); 187 | name = "Thin Binary"; 188 | outputPaths = ( 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | shellPath = /bin/sh; 192 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 193 | }; 194 | 9740EEB61CF901F6004384FC /* Run Script */ = { 195 | isa = PBXShellScriptBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | inputPaths = ( 200 | ); 201 | name = "Run Script"; 202 | outputPaths = ( 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | shellPath = /bin/sh; 206 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 207 | }; 208 | /* End PBXShellScriptBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | 97C146EA1CF9000F007C117D /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 216 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXVariantGroup section */ 223 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C146FB1CF9000F007C117D /* Base */, 227 | ); 228 | name = Main.storyboard; 229 | sourceTree = ""; 230 | }; 231 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | 97C147001CF9000F007C117D /* Base */, 235 | ); 236 | name = LaunchScreen.storyboard; 237 | sourceTree = ""; 238 | }; 239 | /* End PBXVariantGroup section */ 240 | 241 | /* Begin XCBuildConfiguration section */ 242 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 243 | isa = XCBuildConfiguration; 244 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_ANALYZER_NONNULL = YES; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_ENABLE_MODULES = YES; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_COMMA = YES; 255 | CLANG_WARN_CONSTANT_CONVERSION = YES; 256 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 263 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 264 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 267 | CLANG_WARN_STRICT_PROTOTYPES = YES; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 274 | ENABLE_NS_ASSERTIONS = NO; 275 | ENABLE_STRICT_OBJC_MSGSEND = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_NO_COMMON_BLOCKS = YES; 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 285 | MTL_ENABLE_DEBUG_INFO = NO; 286 | SDKROOT = iphoneos; 287 | SUPPORTED_PLATFORMS = iphoneos; 288 | TARGETED_DEVICE_FAMILY = "1,2"; 289 | VALIDATE_PRODUCT = YES; 290 | }; 291 | name = Profile; 292 | }; 293 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 294 | isa = XCBuildConfiguration; 295 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 296 | buildSettings = { 297 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 298 | CLANG_ENABLE_MODULES = YES; 299 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 300 | ENABLE_BITCODE = NO; 301 | FRAMEWORK_SEARCH_PATHS = ( 302 | "$(inherited)", 303 | "$(PROJECT_DIR)/Flutter", 304 | ); 305 | INFOPLIST_FILE = Runner/Info.plist; 306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 307 | LIBRARY_SEARCH_PATHS = ( 308 | "$(inherited)", 309 | "$(PROJECT_DIR)/Flutter", 310 | ); 311 | PRODUCT_BUNDLE_IDENTIFIER = com.example.voicefilter; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 314 | SWIFT_VERSION = 5.0; 315 | VERSIONING_SYSTEM = "apple-generic"; 316 | }; 317 | name = Profile; 318 | }; 319 | 97C147031CF9000F007C117D /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 322 | buildSettings = { 323 | ALWAYS_SEARCH_USER_PATHS = NO; 324 | CLANG_ANALYZER_NONNULL = YES; 325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 326 | CLANG_CXX_LIBRARY = "libc++"; 327 | CLANG_ENABLE_MODULES = YES; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_COMMA = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_EMPTY_BODY = YES; 336 | CLANG_WARN_ENUM_CONVERSION = YES; 337 | CLANG_WARN_INFINITE_RECURSION = YES; 338 | CLANG_WARN_INT_CONVERSION = YES; 339 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 340 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 344 | CLANG_WARN_STRICT_PROTOTYPES = YES; 345 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 346 | CLANG_WARN_UNREACHABLE_CODE = YES; 347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 349 | COPY_PHASE_STRIP = NO; 350 | DEBUG_INFORMATION_FORMAT = dwarf; 351 | ENABLE_STRICT_OBJC_MSGSEND = YES; 352 | ENABLE_TESTABILITY = YES; 353 | GCC_C_LANGUAGE_STANDARD = gnu99; 354 | GCC_DYNAMIC_NO_PIC = NO; 355 | GCC_NO_COMMON_BLOCKS = YES; 356 | GCC_OPTIMIZATION_LEVEL = 0; 357 | GCC_PREPROCESSOR_DEFINITIONS = ( 358 | "DEBUG=1", 359 | "$(inherited)", 360 | ); 361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 363 | GCC_WARN_UNDECLARED_SELECTOR = YES; 364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 365 | GCC_WARN_UNUSED_FUNCTION = YES; 366 | GCC_WARN_UNUSED_VARIABLE = YES; 367 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 368 | MTL_ENABLE_DEBUG_INFO = YES; 369 | ONLY_ACTIVE_ARCH = YES; 370 | SDKROOT = iphoneos; 371 | TARGETED_DEVICE_FAMILY = "1,2"; 372 | }; 373 | name = Debug; 374 | }; 375 | 97C147041CF9000F007C117D /* Release */ = { 376 | isa = XCBuildConfiguration; 377 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 378 | buildSettings = { 379 | ALWAYS_SEARCH_USER_PATHS = NO; 380 | CLANG_ANALYZER_NONNULL = YES; 381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 382 | CLANG_CXX_LIBRARY = "libc++"; 383 | CLANG_ENABLE_MODULES = YES; 384 | CLANG_ENABLE_OBJC_ARC = YES; 385 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 386 | CLANG_WARN_BOOL_CONVERSION = YES; 387 | CLANG_WARN_COMMA = YES; 388 | CLANG_WARN_CONSTANT_CONVERSION = YES; 389 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 390 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 391 | CLANG_WARN_EMPTY_BODY = YES; 392 | CLANG_WARN_ENUM_CONVERSION = YES; 393 | CLANG_WARN_INFINITE_RECURSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNREACHABLE_CODE = YES; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | COPY_PHASE_STRIP = NO; 406 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 407 | ENABLE_NS_ASSERTIONS = NO; 408 | ENABLE_STRICT_OBJC_MSGSEND = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu99; 410 | GCC_NO_COMMON_BLOCKS = YES; 411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 413 | GCC_WARN_UNDECLARED_SELECTOR = YES; 414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 415 | GCC_WARN_UNUSED_FUNCTION = YES; 416 | GCC_WARN_UNUSED_VARIABLE = YES; 417 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 418 | MTL_ENABLE_DEBUG_INFO = NO; 419 | SDKROOT = iphoneos; 420 | SUPPORTED_PLATFORMS = iphoneos; 421 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 422 | TARGETED_DEVICE_FAMILY = "1,2"; 423 | VALIDATE_PRODUCT = YES; 424 | }; 425 | name = Release; 426 | }; 427 | 97C147061CF9000F007C117D /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | CLANG_ENABLE_MODULES = YES; 433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 434 | ENABLE_BITCODE = NO; 435 | FRAMEWORK_SEARCH_PATHS = ( 436 | "$(inherited)", 437 | "$(PROJECT_DIR)/Flutter", 438 | ); 439 | INFOPLIST_FILE = Runner/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 441 | LIBRARY_SEARCH_PATHS = ( 442 | "$(inherited)", 443 | "$(PROJECT_DIR)/Flutter", 444 | ); 445 | PRODUCT_BUNDLE_IDENTIFIER = com.example.voicefilter; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 449 | SWIFT_VERSION = 5.0; 450 | VERSIONING_SYSTEM = "apple-generic"; 451 | }; 452 | name = Debug; 453 | }; 454 | 97C147071CF9000F007C117D /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 457 | buildSettings = { 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | CLANG_ENABLE_MODULES = YES; 460 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 461 | ENABLE_BITCODE = NO; 462 | FRAMEWORK_SEARCH_PATHS = ( 463 | "$(inherited)", 464 | "$(PROJECT_DIR)/Flutter", 465 | ); 466 | INFOPLIST_FILE = Runner/Info.plist; 467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 468 | LIBRARY_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "$(PROJECT_DIR)/Flutter", 471 | ); 472 | PRODUCT_BUNDLE_IDENTIFIER = com.example.voicefilter; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 475 | SWIFT_VERSION = 5.0; 476 | VERSIONING_SYSTEM = "apple-generic"; 477 | }; 478 | name = Release; 479 | }; 480 | /* End XCBuildConfiguration section */ 481 | 482 | /* Begin XCConfigurationList section */ 483 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | 97C147031CF9000F007C117D /* Debug */, 487 | 97C147041CF9000F007C117D /* Release */, 488 | 249021D3217E4FDB00AE95B9 /* Profile */, 489 | ); 490 | defaultConfigurationIsVisible = 0; 491 | defaultConfigurationName = Release; 492 | }; 493 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 494 | isa = XCConfigurationList; 495 | buildConfigurations = ( 496 | 97C147061CF9000F007C117D /* Debug */, 497 | 97C147071CF9000F007C117D /* Release */, 498 | 249021D4217E4FDB00AE95B9 /* Profile */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | /* End XCConfigurationList section */ 504 | }; 505 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 506 | } 507 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | voicefilter 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /flutter app/voicefilter/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:voicefilter/services/auth_manager.dart'; 3 | import 'package:voicefilter/utilities/constants.dart'; 4 | 5 | void main() { 6 | runApp(MyApp()); 7 | } 8 | 9 | class MyApp extends StatelessWidget { 10 | // This widget is the root of your application. 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'voice filter', 15 | debugShowCheckedModeBanner: false, 16 | theme: ThemeData( 17 | primaryColor: myBlue, 18 | primarySwatch: Colors.blue, 19 | visualDensity: VisualDensity.adaptivePlatformDensity, 20 | ), 21 | home: AuthManager(), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/screens/embedding_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io' as io; 3 | import 'package:file/file.dart'; 4 | import 'package:firebase_storage/firebase_storage.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 7 | import 'package:path_provider/path_provider.dart'; 8 | import 'package:flutter_audio_recorder/flutter_audio_recorder.dart'; 9 | import 'package:file/local.dart'; 10 | import 'package:voicefilter/screens/filter_screen.dart'; 11 | import 'package:voicefilter/services/auth_service.dart'; 12 | import 'package:voicefilter/utilities/constants.dart'; 13 | import 'package:firebase_database/firebase_database.dart'; 14 | import 'package:firebase_auth/firebase_auth.dart'; 15 | 16 | class EmbeddingScreen extends StatefulWidget { 17 | final LocalFileSystem localFileSystem; 18 | EmbeddingScreen({localFileSystem}) 19 | : this.localFileSystem = localFileSystem ?? LocalFileSystem(); 20 | @override 21 | _EmbeddingScreenState createState() => _EmbeddingScreenState(); 22 | } 23 | 24 | class _EmbeddingScreenState extends State { 25 | FlutterAudioRecorder _recorder; 26 | Recording _current; 27 | RecordingStatus _currentStatus = RecordingStatus.Unset; 28 | 29 | _init() async { 30 | try { 31 | if (await FlutterAudioRecorder.hasPermissions) { 32 | String customPath = '/embedding_'; 33 | io.Directory appDocDirectory; 34 | if (io.Platform.isIOS) { 35 | appDocDirectory = await getApplicationDocumentsDirectory(); 36 | } else { 37 | appDocDirectory = await getExternalStorageDirectory(); 38 | } 39 | 40 | // can add extension like ".mp4" ".wav" ".m4a" ".aac" 41 | customPath = 42 | appDocDirectory.path + customPath + DateTime.now().toString(); 43 | 44 | _recorder = 45 | FlutterAudioRecorder(customPath, audioFormat: AudioFormat.WAV); 46 | 47 | await _recorder.initialized; 48 | // after initialization 49 | var current = await _recorder.current(channel: 0); 50 | print(current); 51 | // should be "Initialized", if all working fine 52 | setState(() { 53 | _current = current; 54 | _currentStatus = current.status; 55 | print(_currentStatus); 56 | }); 57 | } else { 58 | Scaffold.of(context).showSnackBar( 59 | SnackBar(content: Text("You must accept permissions"))); 60 | } 61 | } catch (e) { 62 | print(e); 63 | } 64 | } 65 | 66 | @override 67 | void initState() { 68 | super.initState(); 69 | _init(); 70 | } 71 | 72 | @override 73 | Widget build(BuildContext context) { 74 | double width = MediaQuery.of(context).size.width; 75 | return SafeArea( 76 | child: Scaffold( 77 | backgroundColor: Colors.white, 78 | body: _currentStatus == RecordingStatus.Unset 79 | ? Center( 80 | child: CircularProgressIndicator( 81 | valueColor: AlwaysStoppedAnimation( 82 | myBlue, 83 | ), 84 | ), 85 | ) 86 | : Column( 87 | children: [ 88 | Expanded( 89 | child: SingleChildScrollView( 90 | child: Column( 91 | crossAxisAlignment: CrossAxisAlignment.start, 92 | mainAxisAlignment: MainAxisAlignment.spaceAround, 93 | children: [ 94 | SizedBox( 95 | height: 20, 96 | ), 97 | Image.asset( 98 | 'assets/audio1.png', 99 | width: width, 100 | ), 101 | SizedBox( 102 | height: 40, 103 | ), 104 | Container( 105 | padding: EdgeInsets.symmetric( 106 | horizontal: 20, 107 | ), 108 | child: Text( 109 | "Welcome! thank you for signing up\nCan you please greet us with a 'hello'\nWe'll use it as your reference speech for the voice filter", 110 | textScaleFactor: 1.1, 111 | style: TextStyle( 112 | letterSpacing: 1.1, 113 | color: Colors.black54, 114 | fontWeight: FontWeight.w700, 115 | fontFamily: 'Raleway', 116 | ), 117 | ), 118 | ), 119 | ], 120 | ), 121 | ), 122 | ), 123 | Row( 124 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 125 | children: [ 126 | IconButton( 127 | icon: Icon( 128 | FontAwesomeIcons.stopCircle, 129 | color: myBlue, 130 | ), 131 | onPressed: _currentStatus != RecordingStatus.Unset 132 | ? _stop 133 | : null, 134 | ), 135 | Column( 136 | children: [ 137 | _buildText(_currentStatus), 138 | SizedBox( 139 | height: 10, 140 | ), 141 | InkWell( 142 | onTap: micResponse, 143 | child: CircleAvatar( 144 | backgroundColor: myBlue, 145 | radius: 25, 146 | child: Icon( 147 | Icons.mic, 148 | color: Colors.white, 149 | ), 150 | ), 151 | ), 152 | SizedBox( 153 | height: 20, 154 | ), 155 | ], 156 | ), 157 | IconButton( 158 | icon: Icon( 159 | FontAwesomeIcons.signOutAlt, 160 | color: myBlue, 161 | ), 162 | onPressed: _logout, 163 | ), 164 | ], 165 | ), 166 | ], 167 | ), 168 | ), 169 | ); 170 | } 171 | 172 | void micResponse() { 173 | switch (_currentStatus) { 174 | case RecordingStatus.Initialized: 175 | { 176 | _start(); 177 | break; 178 | } 179 | case RecordingStatus.Recording: 180 | { 181 | _pause(); 182 | break; 183 | } 184 | case RecordingStatus.Paused: 185 | { 186 | _resume(); 187 | break; 188 | } 189 | case RecordingStatus.Stopped: 190 | { 191 | _init(); 192 | break; 193 | } 194 | default: 195 | break; 196 | } 197 | } 198 | 199 | Future _logout() async { 200 | await FirebaseAuthentication().signOut(context); 201 | } 202 | 203 | _start() async { 204 | try { 205 | await _recorder.start(); 206 | var recording = await _recorder.current(channel: 0); 207 | setState(() { 208 | _current = recording; 209 | }); 210 | 211 | const tick = const Duration(milliseconds: 50); 212 | Timer.periodic(tick, (Timer t) async { 213 | if (_currentStatus == RecordingStatus.Stopped) { 214 | t.cancel(); 215 | } 216 | 217 | var current = await _recorder.current(channel: 0); 218 | setState(() { 219 | _current = current; 220 | _currentStatus = _current.status; 221 | }); 222 | }); 223 | } catch (e) { 224 | print(e); 225 | } 226 | } 227 | 228 | _resume() async { 229 | await _recorder.resume(); 230 | setState(() {}); 231 | } 232 | 233 | _pause() async { 234 | await _recorder.pause(); 235 | setState(() {}); 236 | } 237 | 238 | Future uploadReferenceSpeech() async { 239 | FirebaseUser user = await FirebaseAuth.instance.currentUser(); 240 | DatabaseReference dbRef = FirebaseDatabase.instance.reference(); 241 | final StorageReference storageRef = FirebaseStorage.instance.ref(); 242 | io.File audioFile = io.File(_current.path); 243 | 244 | final StorageUploadTask uploadTask = storageRef 245 | .child("ref_speech") 246 | .child(user.email + ".wav") 247 | .putFile(audioFile); 248 | var audioUrl = await (await uploadTask.onComplete).ref.getDownloadURL(); 249 | print(audioUrl); 250 | 251 | dbRef.child(user.email.split('@')[0]).update({ 252 | 'embedding': audioUrl, 253 | }); 254 | } 255 | 256 | _stop() async { 257 | var result = await _recorder.stop(); 258 | print("Stop recording: ${result.path}"); 259 | print("Stop recording: ${result.duration}"); 260 | File file = widget.localFileSystem.file(result.path); 261 | print("File length: ${await file.length()}"); 262 | 263 | setState(() { 264 | _current = result; 265 | _currentStatus = _current.status; 266 | }); 267 | 268 | await uploadReferenceSpeech().whenComplete(() { 269 | Navigator.pushReplacement( 270 | context, 271 | MaterialPageRoute( 272 | builder: (context) => FilterScreen(), 273 | ), 274 | ); 275 | }); 276 | } 277 | 278 | Widget _buildText(RecordingStatus status) { 279 | var text = ""; 280 | switch (_currentStatus) { 281 | case RecordingStatus.Initialized: 282 | { 283 | text = 'Start'; 284 | break; 285 | } 286 | case RecordingStatus.Recording: 287 | { 288 | text = 'Pause'; 289 | break; 290 | } 291 | case RecordingStatus.Paused: 292 | { 293 | text = 'Resume'; 294 | break; 295 | } 296 | case RecordingStatus.Stopped: 297 | { 298 | text = 'Initialize'; 299 | break; 300 | } 301 | default: 302 | break; 303 | } 304 | return Text( 305 | text, 306 | style: TextStyle( 307 | color: myBlue, 308 | letterSpacing: 1.4, 309 | fontWeight: FontWeight.w900, 310 | fontFamily: 'Spartan', 311 | ), 312 | ); 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/screens/filter_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io' as io; 3 | import 'package:file/file.dart'; 4 | import 'package:firebase_database/firebase_database.dart'; 5 | import 'package:firebase_storage/firebase_storage.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 8 | import 'package:path_provider/path_provider.dart'; 9 | import 'package:flutter_audio_recorder/flutter_audio_recorder.dart'; 10 | import 'package:file/local.dart'; 11 | import 'package:voicefilter/services/api.dart'; 12 | import 'package:voicefilter/services/auth_service.dart'; 13 | import 'package:voicefilter/utilities/constants.dart'; 14 | import 'package:voicefilter/widgets/custom_painter.dart'; 15 | import 'package:voicefilter/widgets/player_widget.dart'; 16 | import 'package:firebase_auth/firebase_auth.dart'; 17 | 18 | class FilterScreen extends StatefulWidget { 19 | @override 20 | _FilterScreenState createState() => _FilterScreenState(); 21 | } 22 | 23 | class UserData { 24 | String userEmail; 25 | String refUrl; 26 | UserData(this.userEmail, this.refUrl); 27 | } 28 | 29 | class _FilterScreenState extends State { 30 | Future getUserData() async { 31 | String userEmail; 32 | String refUrl; 33 | FirebaseUser user = await FirebaseAuth.instance.currentUser(); 34 | userEmail = user.email.split('@')[0]; 35 | DatabaseReference dbRef = 36 | FirebaseDatabase.instance.reference().child(userEmail); 37 | await dbRef.once().then((DataSnapshot snapshot) { 38 | refUrl = snapshot.value["embedding"]; 39 | print("user :" + userEmail); 40 | print("ref :" + refUrl); 41 | }); 42 | 43 | return UserData(userEmail, refUrl); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return FutureBuilder( 49 | future: getUserData(), 50 | builder: (context, snapshot) { 51 | if (snapshot.hasData) { 52 | return VoiceFilter( 53 | userData: snapshot.data, 54 | ); 55 | } else 56 | return Scaffold( 57 | backgroundColor: Colors.white, 58 | body: Center( 59 | child: CircularProgressIndicator( 60 | valueColor: AlwaysStoppedAnimation(myBlue), 61 | ), 62 | ), 63 | ); 64 | }, 65 | ); 66 | } 67 | } 68 | 69 | class VoiceFilter extends StatefulWidget { 70 | final UserData userData; 71 | final LocalFileSystem localFileSystem; 72 | VoiceFilter({ 73 | localFileSystem, 74 | this.userData, 75 | }) : this.localFileSystem = localFileSystem ?? LocalFileSystem(); 76 | @override 77 | _VoiceFilterState createState() => _VoiceFilterState(); 78 | } 79 | 80 | class _VoiceFilterState extends State { 81 | FlutterAudioRecorder _recorder; 82 | Recording _current; 83 | RecordingStatus _currentStatus = RecordingStatus.Unset; 84 | String timeKey; 85 | 86 | @override 87 | void initState() { 88 | super.initState(); 89 | _init(); 90 | print("init 2:"); 91 | print(widget.userData.refUrl); 92 | } 93 | 94 | Widget getCirclePainter() { 95 | double percentage = ((120 + _current.metering.averagePower) / 1.2); 96 | return Container( 97 | height: 50, 98 | width: 50, 99 | child: CustomPaint( 100 | foregroundPainter: CirclePainter( 101 | lineColor: myBlue.withOpacity(0.3), 102 | completeColor: myBlue, 103 | completePercent: percentage, 104 | width: 8, 105 | ), 106 | ), 107 | ); 108 | } 109 | 110 | Widget underlinedText(text) { 111 | double width = MediaQuery.of(context).size.width; 112 | return Padding( 113 | padding: const EdgeInsets.only( 114 | left: 25, 115 | ), 116 | child: Column( 117 | crossAxisAlignment: CrossAxisAlignment.start, 118 | children: [ 119 | SizedBox( 120 | height: 20, 121 | ), 122 | Text( 123 | text, 124 | textScaleFactor: 0.9, 125 | style: TextStyle( 126 | letterSpacing: 1.1, 127 | color: Colors.black54, 128 | fontWeight: FontWeight.w700, 129 | fontFamily: 'Raleway', 130 | ), 131 | ), 132 | Divider( 133 | color: myBlue, 134 | thickness: 2, 135 | indent: width * 0.01, 136 | endIndent: width * 0.78, 137 | ), 138 | SizedBox( 139 | height: 10, 140 | ), 141 | ], 142 | ), 143 | ); 144 | } 145 | 146 | @override 147 | Widget build(BuildContext context) { 148 | double width = MediaQuery.of(context).size.width; 149 | return SafeArea( 150 | child: Scaffold( 151 | backgroundColor: Colors.white, 152 | body: _currentStatus == RecordingStatus.Unset 153 | ? Center( 154 | child: CircularProgressIndicator( 155 | valueColor: AlwaysStoppedAnimation( 156 | myBlue, 157 | ), 158 | ), 159 | ) 160 | : Column( 161 | children: [ 162 | Expanded( 163 | child: SingleChildScrollView( 164 | child: Column( 165 | crossAxisAlignment: CrossAxisAlignment.start, 166 | mainAxisAlignment: MainAxisAlignment.spaceAround, 167 | children: [ 168 | SizedBox( 169 | height: 20, 170 | ), 171 | Row( 172 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 173 | children: [ 174 | Image.asset( 175 | 'assets/audio2.png', 176 | width: width * 0.55, 177 | ), 178 | getCirclePainter(), 179 | Text( 180 | _current.duration.inSeconds.toString() + " s", 181 | style: TextStyle( 182 | color: myBlue, 183 | fontWeight: FontWeight.w700, 184 | ), 185 | ), 186 | Container(), 187 | ], 188 | ), 189 | SizedBox( 190 | height: 40, 191 | ), 192 | timeKey != null ? getInputStream() : Container(), 193 | ], 194 | ), 195 | ), 196 | ), 197 | Row( 198 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 199 | children: [ 200 | IconButton( 201 | icon: Icon( 202 | FontAwesomeIcons.stopCircle, 203 | color: myBlue, 204 | ), 205 | onPressed: _currentStatus != RecordingStatus.Unset 206 | ? _stop 207 | : null, 208 | ), 209 | Column( 210 | children: [ 211 | _buildText(_currentStatus), 212 | SizedBox( 213 | height: 10, 214 | ), 215 | InkWell( 216 | onTap: micResponse, 217 | child: CircleAvatar( 218 | backgroundColor: myBlue, 219 | radius: 25, 220 | child: Icon( 221 | Icons.mic, 222 | color: Colors.white, 223 | ), 224 | ), 225 | ), 226 | SizedBox( 227 | height: 20, 228 | ), 229 | ], 230 | ), 231 | IconButton( 232 | icon: Icon( 233 | FontAwesomeIcons.signOutAlt, 234 | color: myBlue, 235 | ), 236 | onPressed: _logout, 237 | ), 238 | ], 239 | ), 240 | ], 241 | ), 242 | ), 243 | ); 244 | } 245 | 246 | Widget getPlayer(text, url) { 247 | return Column( 248 | children: [ 249 | underlinedText(text), 250 | PlayerWidget( 251 | url: url, 252 | ), 253 | ], 254 | ); 255 | } 256 | 257 | Widget getInputStream() { 258 | return StreamBuilder( 259 | stream: FirebaseDatabase() 260 | .reference() 261 | .child(widget.userData.userEmail) 262 | .child(timeKey) 263 | .onValue, 264 | builder: (context, snap) { 265 | if (snap.hasData && 266 | !snap.hasError && 267 | snap.data.snapshot.value != null) { 268 | var data = snap.data.snapshot.value; 269 | return Column( 270 | children: [ 271 | getPlayer("INPUT AUDIO", data["input"]), 272 | data["output"] == '-' 273 | ? Container() 274 | : getPlayer("FILTERED AUDIO", data["output"]), 275 | ], 276 | ); 277 | } else 278 | return Center( 279 | child: Text( 280 | "Let's get started", 281 | textScaleFactor: 1.1, 282 | style: TextStyle( 283 | letterSpacing: 1.1, 284 | color: Colors.black54, 285 | fontWeight: FontWeight.w700, 286 | fontFamily: 'Raleway', 287 | ), 288 | )); 289 | }, 290 | ); 291 | } 292 | 293 | void micResponse() { 294 | switch (_currentStatus) { 295 | case RecordingStatus.Initialized: 296 | { 297 | _start(); 298 | break; 299 | } 300 | case RecordingStatus.Recording: 301 | { 302 | _pause(); 303 | break; 304 | } 305 | case RecordingStatus.Paused: 306 | { 307 | _resume(); 308 | break; 309 | } 310 | case RecordingStatus.Stopped: 311 | { 312 | _init(); 313 | break; 314 | } 315 | default: 316 | break; 317 | } 318 | } 319 | 320 | Future uploadInputSpeech(String _timeKey) async { 321 | DatabaseReference dbRef = FirebaseDatabase.instance.reference(); 322 | final StorageReference storageRef = FirebaseStorage.instance.ref(); 323 | io.File audioFile = io.File(_current.path); 324 | 325 | final StorageUploadTask uploadTask = storageRef 326 | .child("input_speech") 327 | .child(widget.userData.userEmail + _timeKey + ".wav") 328 | .putFile(audioFile); 329 | var audioUrl = await (await uploadTask.onComplete).ref.getDownloadURL(); 330 | print(audioUrl); 331 | 332 | dbRef.child(widget.userData.userEmail).child(_timeKey).set({ 333 | 'input': audioUrl, 334 | 'output': '-', 335 | }).whenComplete(() async { 336 | await runVoiceFilterBackend( 337 | widget.userData.userEmail, timeKey, audioUrl, widget.userData.refUrl); 338 | }); 339 | } 340 | 341 | _stop() async { 342 | var result = await _recorder.stop(); 343 | print("Stop recording: ${result.path}"); 344 | print("Stop recording: ${result.duration}"); 345 | File file = widget.localFileSystem.file(result.path); 346 | print("File length: ${await file.length()}"); 347 | 348 | setState(() { 349 | _current = result; 350 | _currentStatus = _current.status; 351 | //timeKey = DateTime.now().toString().split('.')[0]; 352 | timeKey = DateTime.now().millisecondsSinceEpoch.toString(); 353 | }); 354 | 355 | await uploadInputSpeech(timeKey); 356 | } 357 | 358 | Future _logout() async { 359 | await FirebaseAuthentication().signOut(context); 360 | } 361 | 362 | _init() async { 363 | try { 364 | if (await FlutterAudioRecorder.hasPermissions) { 365 | String customPath = '/audio_'; 366 | io.Directory appDocDirectory; 367 | if (io.Platform.isIOS) { 368 | appDocDirectory = await getApplicationDocumentsDirectory(); 369 | } else { 370 | appDocDirectory = await getExternalStorageDirectory(); 371 | } 372 | 373 | // can add extension like ".mp4" ".wav" ".m4a" ".aac" 374 | customPath = 375 | appDocDirectory.path + customPath + DateTime.now().toString(); 376 | //DateTime.now().millisecondsSinceEpoch.toString(); 377 | 378 | _recorder = 379 | FlutterAudioRecorder(customPath, audioFormat: AudioFormat.WAV); 380 | 381 | await _recorder.initialized; 382 | // after initialization 383 | var current = await _recorder.current(channel: 0); 384 | print(current); 385 | // should be "Initialized", if all working fine 386 | setState(() { 387 | _current = current; 388 | _currentStatus = current.status; 389 | print(_currentStatus); 390 | }); 391 | } else { 392 | Scaffold.of(context).showSnackBar( 393 | SnackBar(content: Text("You must accept permissions"))); 394 | } 395 | } catch (e) { 396 | print(e); 397 | } 398 | } 399 | 400 | _start() async { 401 | try { 402 | await _recorder.start(); 403 | var recording = await _recorder.current(channel: 0); 404 | setState(() { 405 | _current = recording; 406 | }); 407 | 408 | const tick = const Duration(milliseconds: 50); 409 | Timer.periodic(tick, (Timer t) async { 410 | if (_currentStatus == RecordingStatus.Stopped) { 411 | t.cancel(); 412 | } 413 | 414 | var current = await _recorder.current(channel: 0); 415 | setState(() { 416 | _current = current; 417 | _currentStatus = _current.status; 418 | }); 419 | }); 420 | } catch (e) { 421 | print(e); 422 | } 423 | } 424 | 425 | _resume() async { 426 | await _recorder.resume(); 427 | setState(() {}); 428 | } 429 | 430 | _pause() async { 431 | await _recorder.pause(); 432 | setState(() {}); 433 | } 434 | 435 | Widget _buildText(RecordingStatus status) { 436 | var text = ""; 437 | switch (_currentStatus) { 438 | case RecordingStatus.Initialized: 439 | { 440 | text = 'Start'; 441 | break; 442 | } 443 | case RecordingStatus.Recording: 444 | { 445 | text = 'Pause'; 446 | break; 447 | } 448 | case RecordingStatus.Paused: 449 | { 450 | text = 'Resume'; 451 | break; 452 | } 453 | case RecordingStatus.Stopped: 454 | { 455 | text = 'Initialize'; 456 | break; 457 | } 458 | default: 459 | break; 460 | } 461 | return Text( 462 | text, 463 | style: TextStyle( 464 | color: myBlue, 465 | letterSpacing: 1.4, 466 | fontWeight: FontWeight.w900, 467 | fontFamily: 'Spartan', 468 | ), 469 | ); 470 | } 471 | } 472 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/screens/login_register_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:voicefilter/services/auth_service.dart'; 3 | import 'package:voicefilter/widgets/dialogbox.dart'; 4 | import 'package:voicefilter/utilities/constants.dart'; 5 | 6 | class LoginRegisterScreen extends StatefulWidget { 7 | @override 8 | _LoginRegisterScreenState createState() => _LoginRegisterScreenState(); 9 | } 10 | 11 | class _LoginRegisterScreenState extends State { 12 | DialogBox dialogBox = DialogBox(); 13 | 14 | final _formKey = GlobalKey(); 15 | 16 | bool login = true; 17 | 18 | String _email = ""; 19 | String _password = ""; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | double width = MediaQuery.of(context).size.width; 24 | return Scaffold( 25 | backgroundColor: Colors.white, 26 | body: Form( 27 | key: _formKey, 28 | child: SingleChildScrollView( 29 | child: Column( 30 | mainAxisAlignment: MainAxisAlignment.center, 31 | crossAxisAlignment: CrossAxisAlignment.center, 32 | children: [ 33 | SizedBox( 34 | height: 50, 35 | ), 36 | Image.asset( 37 | "assets/audio3.png", 38 | width: 0.6 * width, 39 | ), 40 | SizedBox( 41 | height: 15, 42 | ), 43 | Text( 44 | "Voice Filter", 45 | style: TextStyle( 46 | fontFamily: "Spartan", 47 | fontSize: 30, 48 | color: myBlue, 49 | letterSpacing: 1, 50 | fontWeight: FontWeight.w900, 51 | ), 52 | ), 53 | SizedBox( 54 | height: 20, 55 | ), 56 | Container( 57 | margin: EdgeInsets.symmetric( 58 | horizontal: 20, 59 | ), 60 | decoration: BoxDecoration( 61 | color: Colors.white, 62 | borderRadius: BorderRadius.circular(12.0), 63 | boxShadow: [ 64 | BoxShadow( 65 | color: Colors.black12, 66 | offset: Offset(0, 5), 67 | blurRadius: 15, 68 | ), 69 | ]), 70 | child: Container( 71 | padding: EdgeInsets.only(left: 20, right: 20, bottom: 25), 72 | child: Column( 73 | children: screenInputs(), 74 | ), 75 | ), 76 | ), 77 | Container( 78 | child: Column( 79 | children: screenButtons(), 80 | ), 81 | ), 82 | ], 83 | ), 84 | ), 85 | ), 86 | ); 87 | } 88 | 89 | List screenInputs() { 90 | return [ 91 | TextFormField( 92 | style: TextStyle( 93 | color: Colors.black, 94 | fontFamily: 'Spartan', 95 | fontSize: 16, 96 | fontWeight: FontWeight.bold), 97 | decoration: InputDecoration( 98 | labelText: 'Email', 99 | labelStyle: TextStyle( 100 | color: Colors.grey[700], 101 | fontFamily: 'Montserrat', 102 | fontSize: 14, 103 | ), 104 | ), 105 | validator: (value) { 106 | return value.isEmpty ? 'Email is required' : null; 107 | }, 108 | onSaved: (value) { 109 | return _email = value; 110 | }, 111 | ), 112 | SizedBox( 113 | height: 10, 114 | ), 115 | TextFormField( 116 | style: TextStyle( 117 | color: Colors.black, 118 | fontFamily: 'Spartan', 119 | fontSize: 16, 120 | fontWeight: FontWeight.bold), 121 | decoration: InputDecoration( 122 | labelText: 'Password', 123 | labelStyle: TextStyle( 124 | color: Colors.grey[700], 125 | fontFamily: 'Montserrat', 126 | fontSize: 14, 127 | ), 128 | ), 129 | obscureText: true, 130 | validator: (value) { 131 | return value.isEmpty ? 'Password is required' : null; 132 | }, 133 | onSaved: (value) { 134 | return _password = value; 135 | }, 136 | ), 137 | ]; 138 | } 139 | 140 | List screenButtons() { 141 | if (login) { 142 | return [ 143 | SizedBox( 144 | height: 20, 145 | ), 146 | InkWell( 147 | onTap: submitForm, 148 | child: Container( 149 | width: 100, 150 | decoration: BoxDecoration( 151 | color: myBlue, 152 | borderRadius: BorderRadius.circular(6.0), 153 | ), 154 | child: Center( 155 | child: Padding( 156 | padding: EdgeInsets.symmetric(vertical: 10), 157 | child: Text( 158 | "LOGIN", 159 | style: TextStyle( 160 | fontFamily: 'Spartan', 161 | color: Colors.white, 162 | fontWeight: FontWeight.bold, 163 | letterSpacing: 1.5), 164 | ), 165 | ), 166 | ), 167 | ), 168 | ), 169 | FlatButton( 170 | child: Text( 171 | "Don't have an account? Register", 172 | style: 173 | TextStyle(color: myBlue, fontFamily: 'Poppins', fontSize: 12), 174 | ), 175 | onPressed: () { 176 | setState(() { 177 | login = !login; 178 | }); 179 | }, 180 | ) 181 | ]; 182 | } else { 183 | return [ 184 | SizedBox( 185 | height: 20, 186 | ), 187 | InkWell( 188 | onTap: submitForm, 189 | child: Container( 190 | width: 120, 191 | decoration: BoxDecoration( 192 | color: myBlue, 193 | borderRadius: BorderRadius.circular(6.0), 194 | ), 195 | child: Center( 196 | child: Padding( 197 | padding: EdgeInsets.symmetric(vertical: 10), 198 | child: Text( 199 | "REGISTER", 200 | style: TextStyle( 201 | fontFamily: 'Spartan', 202 | color: Colors.white, 203 | fontWeight: FontWeight.bold, 204 | letterSpacing: 1.5, 205 | ), 206 | ), 207 | ), 208 | ), 209 | ), 210 | ), 211 | FlatButton( 212 | child: Text( 213 | "Don't have an account? Register", 214 | style: TextStyle( 215 | color: myBlue, 216 | fontFamily: 'Poppins', 217 | fontSize: 12, 218 | ), 219 | ), 220 | onPressed: () { 221 | setState(() { 222 | login = !login; 223 | }); 224 | }, 225 | ) 226 | ]; 227 | } 228 | } 229 | 230 | void submitForm() async { 231 | print("submi form"); 232 | if (_formKey.currentState.validate()) { 233 | _formKey.currentState.save(); 234 | 235 | try { 236 | if (login) { 237 | await FirebaseAuthentication().signIn(context, _email, _password); 238 | } else { 239 | await FirebaseAuthentication().signUp(context, _email, _password); 240 | } 241 | } catch (e) { 242 | print(e); 243 | DialogBox().information(context, "ERROR", e.toString()); 244 | } 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/services/api.dart: -------------------------------------------------------------------------------- 1 | import 'package:http/http.dart' as http; 2 | import 'dart:convert'; 3 | 4 | String postUrl = "< API KEY >"; 5 | 6 | Future runVoiceFilterBackend( 7 | String userId, 8 | String timeId, 9 | String input, 10 | String ref, 11 | ) async { 12 | Map data = { 13 | 'user_id': userId, 14 | 'time_id': timeId, 15 | 'input_url': input, 16 | 'ref_url': ref, 17 | }; 18 | 19 | //encode Map to JSON 20 | var body = json.encode(data); 21 | var response = await http.post( 22 | postUrl, 23 | body: body, 24 | ); 25 | print("${response.statusCode}"); 26 | } 27 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/services/auth_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:voicefilter/screens/filter_screen.dart'; 4 | import 'package:voicefilter/screens/login_register_screen.dart'; 5 | import 'package:voicefilter/utilities/constants.dart'; 6 | 7 | class AuthManager extends StatefulWidget { 8 | @override 9 | _AuthManagerState createState() => _AuthManagerState(); 10 | } 11 | 12 | class _AuthManagerState extends State { 13 | FirebaseUser user; 14 | 15 | Future getUserData() async { 16 | user = await FirebaseAuth.instance.currentUser(); 17 | } 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return FutureBuilder( 22 | future: getUserData(), 23 | builder: (context, futureSnapshot) { 24 | if (futureSnapshot.connectionState == ConnectionState.waiting) { 25 | return Scaffold( 26 | backgroundColor: Colors.white, 27 | body: Center( 28 | child: CircularProgressIndicator( 29 | valueColor: AlwaysStoppedAnimation( 30 | myBlue, 31 | ), 32 | ), 33 | ), 34 | ); 35 | } else if (futureSnapshot.connectionState == ConnectionState.done && 36 | user != null) { 37 | print('valid user'); 38 | return FilterScreen(); 39 | } else { 40 | print('No user'); 41 | return LoginRegisterScreen(); 42 | } 43 | }, 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/services/auth_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_auth/firebase_auth.dart'; 2 | import 'package:firebase_database/firebase_database.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:voicefilter/screens/embedding_screen.dart'; 5 | import 'package:voicefilter/screens/filter_screen.dart'; 6 | import 'package:voicefilter/screens/login_register_screen.dart'; 7 | import '../widgets/dialogBox.dart'; 8 | 9 | class FirebaseAuthentication { 10 | Future signIn(context, email, password) async { 11 | try { 12 | AuthResult result = 13 | await FirebaseAuth.instance.signInWithEmailAndPassword( 14 | email: email, 15 | password: password, 16 | ); 17 | print(result); 18 | 19 | DatabaseReference dbRef = FirebaseDatabase.instance 20 | .reference() 21 | .child(result.user.email.split('@')[0]); 22 | dbRef.once().then((DataSnapshot snapshot) { 23 | String val = snapshot.value["embedding"]; 24 | if (val == '-') { 25 | Navigator.pushReplacement( 26 | context, 27 | MaterialPageRoute( 28 | builder: (context) => EmbeddingScreen(), 29 | ), 30 | ); 31 | } else { 32 | Navigator.pushReplacement( 33 | context, 34 | MaterialPageRoute( 35 | builder: (context) => FilterScreen(), 36 | ), 37 | ); 38 | } 39 | }); 40 | } catch (e) { 41 | print("signin error:" + e.toString()); 42 | DialogBox() 43 | .information(context, "ALERT", "Your login details are incorrect"); 44 | } 45 | } 46 | 47 | Future signUp(context, email, password) async { 48 | try { 49 | AuthResult result = 50 | await FirebaseAuth.instance.createUserWithEmailAndPassword( 51 | email: email, 52 | password: password, 53 | ); 54 | print(result); 55 | 56 | DatabaseReference dbRef = FirebaseDatabase.instance.reference(); 57 | dbRef.child(result.user.email.split('@')[0]).set({ 58 | 'embedding': '-', 59 | }); 60 | 61 | Navigator.pushReplacement( 62 | context, 63 | MaterialPageRoute( 64 | builder: (context) => EmbeddingScreen(), 65 | ), 66 | ); 67 | } catch (e) { 68 | DialogBox().information(context, "ERROR", e.toString()); 69 | print(e); 70 | return e; 71 | } 72 | } 73 | 74 | Future signOut(context) async { 75 | await FirebaseAuth.instance.signOut().then( 76 | (value) => Navigator.pushReplacement( 77 | context, 78 | MaterialPageRoute( 79 | builder: (context) => LoginRegisterScreen(), 80 | ), 81 | ), 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/utilities/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | Color myBlue = Color(0xff536DFE); 4 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/widgets/custom_painter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import 'package:flutter/material.dart'; 3 | import 'dart:math'; 4 | 5 | class CirclePainter extends CustomPainter { 6 | Color lineColor; 7 | Color completeColor; 8 | double completePercent; 9 | double width; 10 | CirclePainter( 11 | {this.lineColor, this.completeColor, this.completePercent, this.width}); 12 | @override 13 | void paint(Canvas canvas, Size size) { 14 | Paint line = new Paint() 15 | ..color = lineColor 16 | ..strokeCap = StrokeCap.round 17 | ..style = PaintingStyle.stroke 18 | ..strokeWidth = width; 19 | Paint complete = new Paint() 20 | ..color = completeColor 21 | ..strokeCap = StrokeCap.round 22 | ..style = PaintingStyle.stroke 23 | ..strokeWidth = width; 24 | Offset center = new Offset(size.width / 2, size.height / 2); 25 | double radius = min(size.width / 2, size.height / 2); 26 | canvas.drawCircle(center, radius, line); 27 | double arcAngle = 2 * pi * (completePercent / 100); 28 | canvas.drawArc(new Rect.fromCircle(center: center, radius: radius), -pi / 2, 29 | arcAngle, false, complete); 30 | } 31 | 32 | @override 33 | bool shouldRepaint(CustomPainter oldDelegate) { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/widgets/dialogbox.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 3 | import 'package:voicefilter/utilities/constants.dart'; 4 | 5 | class DialogBox { 6 | information(BuildContext context, String title, String desc) { 7 | print( 8 | "dialog : " + Theme.of(context).primaryColor.toString(), 9 | ); 10 | return showDialog( 11 | context: context, 12 | barrierDismissible: true, 13 | builder: (BuildContext context) { 14 | return AlertDialog( 15 | backgroundColor: Colors.white, 16 | title: Text( 17 | title, 18 | style: TextStyle( 19 | color: myBlue, 20 | fontSize: 30, 21 | fontWeight: FontWeight.bold, 22 | letterSpacing: 0.3, 23 | ), 24 | ), 25 | content: SingleChildScrollView( 26 | child: ListBody( 27 | children: [ 28 | Text( 29 | desc, 30 | style: TextStyle( 31 | fontSize: 12, 32 | color: Colors.black54, 33 | fontWeight: FontWeight.w600, 34 | letterSpacing: 1.2, 35 | ), 36 | ), 37 | ], 38 | ), 39 | ), 40 | actions: [ 41 | FlatButton( 42 | onPressed: () { 43 | return Navigator.pop(context); 44 | }, 45 | child: FaIcon( 46 | FontAwesomeIcons.checkCircle, 47 | color: myBlue, 48 | ), 49 | ), 50 | ], 51 | ); 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /flutter app/voicefilter/lib/widgets/player_widget.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:audioplayers/audioplayers.dart'; 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:voicefilter/utilities/constants.dart'; 6 | 7 | enum PlayerState { stopped, playing, paused } 8 | enum PlayingRouteState { speakers, earpiece } 9 | 10 | class PlayerWidget extends StatefulWidget { 11 | final String url; 12 | final PlayerMode mode; 13 | 14 | PlayerWidget({ 15 | Key key, 16 | @required this.url, 17 | this.mode = PlayerMode.MEDIA_PLAYER, 18 | }) : super(key: key); 19 | 20 | @override 21 | State createState() { 22 | return _PlayerWidgetState(url, mode); 23 | } 24 | } 25 | 26 | class _PlayerWidgetState extends State { 27 | String url; 28 | PlayerMode mode; 29 | 30 | AudioPlayer _audioPlayer; 31 | AudioPlayerState _audioPlayerState; 32 | Duration _duration; 33 | Duration _position; 34 | 35 | PlayerState _playerState = PlayerState.stopped; 36 | PlayingRouteState _playingRouteState = PlayingRouteState.speakers; 37 | StreamSubscription _durationSubscription; 38 | StreamSubscription _positionSubscription; 39 | StreamSubscription _playerCompleteSubscription; 40 | StreamSubscription _playerErrorSubscription; 41 | StreamSubscription _playerStateSubscription; 42 | 43 | get _isPlaying => _playerState == PlayerState.playing; 44 | get _isPaused => _playerState == PlayerState.paused; 45 | get _durationText => _duration?.toString()?.split('.')?.first ?? ''; 46 | get _positionText => _position?.toString()?.split('.')?.first ?? ''; 47 | 48 | get _isPlayingThroughEarpiece => 49 | _playingRouteState == PlayingRouteState.earpiece; 50 | 51 | _PlayerWidgetState(this.url, this.mode); 52 | 53 | @override 54 | void initState() { 55 | super.initState(); 56 | _initAudioPlayer(); 57 | } 58 | 59 | @override 60 | void dispose() { 61 | _audioPlayer.dispose(); 62 | _durationSubscription?.cancel(); 63 | _positionSubscription?.cancel(); 64 | _playerCompleteSubscription?.cancel(); 65 | _playerErrorSubscription?.cancel(); 66 | _playerStateSubscription?.cancel(); 67 | super.dispose(); 68 | } 69 | 70 | @override 71 | Widget build(BuildContext context) { 72 | double width = MediaQuery.of(context).size.width; 73 | return Container( 74 | padding: EdgeInsets.symmetric( 75 | vertical: 10, 76 | horizontal: 10, 77 | ), 78 | decoration: BoxDecoration( 79 | borderRadius: BorderRadius.circular(10), 80 | color: Colors.white, 81 | boxShadow: [ 82 | BoxShadow( 83 | color: Colors.black.withOpacity(.3), 84 | blurRadius: 2.0, 85 | ) 86 | ]), 87 | margin: EdgeInsets.symmetric( 88 | horizontal: width * 0.06, 89 | vertical: 3, 90 | ), 91 | child: Column( 92 | mainAxisSize: MainAxisSize.min, 93 | children: [ 94 | Row( 95 | mainAxisSize: MainAxisSize.min, 96 | children: [ 97 | IconButton( 98 | key: Key('play_button'), 99 | onPressed: _isPlaying ? null : () => _play(), 100 | iconSize: 32, 101 | icon: Icon(Icons.play_arrow), 102 | color: myBlue, 103 | ), 104 | IconButton( 105 | key: Key('pause_button'), 106 | onPressed: _isPlaying ? () => _pause() : null, 107 | iconSize: 32, 108 | icon: Icon(Icons.pause), 109 | color: myBlue, 110 | ), 111 | IconButton( 112 | key: Key('stop_button'), 113 | onPressed: _isPlaying || _isPaused ? () => _stop() : null, 114 | iconSize: 32, 115 | icon: Icon(Icons.stop), 116 | color: myBlue, 117 | ), 118 | ], 119 | ), 120 | Column( 121 | mainAxisSize: MainAxisSize.min, 122 | children: [ 123 | Padding( 124 | padding: EdgeInsets.all(8), 125 | child: Stack( 126 | children: [ 127 | Slider( 128 | activeColor: myBlue, 129 | inactiveColor: Colors.black38, 130 | onChanged: (v) { 131 | final position = v * _duration.inMilliseconds; 132 | _audioPlayer 133 | .seek(Duration(milliseconds: position.round())); 134 | }, 135 | value: (_position != null && 136 | _duration != null && 137 | _position.inMilliseconds > 0 && 138 | _position.inMilliseconds < 139 | _duration.inMilliseconds) 140 | ? _position.inMilliseconds / _duration.inMilliseconds 141 | : 0.0, 142 | ), 143 | ], 144 | ), 145 | ), 146 | Text( 147 | _position != null 148 | ? '${_positionText ?? ''} / ${_durationText ?? ''}' 149 | : _duration != null ? _durationText : '', 150 | style: TextStyle( 151 | fontSize: 12, 152 | letterSpacing: 1, 153 | color: myBlue, 154 | fontFamily: 'Montserrat', 155 | ), 156 | ), 157 | ], 158 | ), 159 | ], 160 | ), 161 | ); 162 | } 163 | 164 | void _initAudioPlayer() { 165 | _audioPlayer = AudioPlayer(mode: mode); 166 | 167 | _durationSubscription = _audioPlayer.onDurationChanged.listen((duration) { 168 | setState(() => _duration = duration); 169 | 170 | //implemented for iOS, waiting for android impl 171 | 172 | if (Theme.of(context).platform == TargetPlatform.iOS) { 173 | // (Optional) listen for notification updates in the background 174 | _audioPlayer.startHeadlessService(); 175 | 176 | // set at least title to see the notification bar on ios. 177 | _audioPlayer.setNotification( 178 | title: 'App Name', 179 | artist: 'Artist or blank', 180 | albumTitle: 'Name or blank', 181 | imageUrl: 'url or blank', 182 | forwardSkipInterval: const Duration(seconds: 30), // default is 30s 183 | backwardSkipInterval: const Duration(seconds: 30), // default is 30s 184 | duration: duration, 185 | elapsedTime: Duration(seconds: 0)); 186 | } 187 | }); 188 | 189 | _positionSubscription = 190 | _audioPlayer.onAudioPositionChanged.listen((p) => setState(() { 191 | _position = p; 192 | })); 193 | 194 | _playerCompleteSubscription = 195 | _audioPlayer.onPlayerCompletion.listen((event) { 196 | _onComplete(); 197 | setState(() { 198 | _position = _duration; 199 | }); 200 | }); 201 | 202 | _playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) { 203 | print('audioPlayer error : $msg'); 204 | setState(() { 205 | _playerState = PlayerState.stopped; 206 | _duration = Duration(seconds: 0); 207 | _position = Duration(seconds: 0); 208 | }); 209 | }); 210 | 211 | _audioPlayer.onPlayerStateChanged.listen((state) { 212 | if (!mounted) return; 213 | setState(() { 214 | _audioPlayerState = state; 215 | }); 216 | }); 217 | 218 | _audioPlayer.onNotificationPlayerStateChanged.listen((state) { 219 | if (!mounted) return; 220 | setState(() => _audioPlayerState = state); 221 | }); 222 | 223 | _playingRouteState = PlayingRouteState.speakers; 224 | } 225 | 226 | Future _play() async { 227 | final playPosition = (_position != null && 228 | _duration != null && 229 | _position.inMilliseconds > 0 && 230 | _position.inMilliseconds < _duration.inMilliseconds) 231 | ? _position 232 | : null; 233 | 234 | print(url); 235 | 236 | final result = await _audioPlayer.play( 237 | url, 238 | position: playPosition, 239 | ); 240 | if (result == 1) setState(() => _playerState = PlayerState.playing); 241 | 242 | // default playback rate is 1.0 243 | // this should be called after _audioPlayer.play() or _audioPlayer.resume() 244 | // this can also be called everytime the user wants to change playback rate in the UI 245 | _audioPlayer.setPlaybackRate(playbackRate: 1.0); 246 | 247 | return result; 248 | } 249 | 250 | Future _pause() async { 251 | final result = await _audioPlayer.pause(); 252 | if (result == 1) setState(() => _playerState = PlayerState.paused); 253 | return result; 254 | } 255 | 256 | Future _earpieceOrSpeakersToggle() async { 257 | final result = await _audioPlayer.earpieceOrSpeakersToggle(); 258 | if (result == 1) 259 | setState(() => _playingRouteState = 260 | _playingRouteState == PlayingRouteState.speakers 261 | ? PlayingRouteState.earpiece 262 | : PlayingRouteState.speakers); 263 | return result; 264 | } 265 | 266 | Future _stop() async { 267 | final result = await _audioPlayer.stop(); 268 | if (result == 1) { 269 | setState(() { 270 | _playerState = PlayerState.stopped; 271 | _position = Duration(); 272 | }); 273 | } 274 | return result; 275 | } 276 | 277 | void _onComplete() { 278 | setState(() => _playerState = PlayerState.stopped); 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /flutter app/voicefilter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: voicefilter 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.7.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | permission_handler: ^5.0.1+1 27 | flutter_audio_recorder: ^0.5.5 28 | file: ^5.2.1 29 | audioplayers: ^0.15.1 30 | firebase_storage: ^3.1.6 31 | firebase_auth: ^0.16.1 32 | cloud_firestore: ^0.13.7 33 | firebase_database: ^3.1.6 34 | font_awesome_flutter: ^8.8.1 35 | dio: ^3.0.9 36 | http: ^0.12.1 37 | 38 | # The following adds the Cupertino Icons font to your application. 39 | # Use with the CupertinoIcons class for iOS style icons. 40 | cupertino_icons: ^0.1.3 41 | 42 | dev_dependencies: 43 | flutter_test: 44 | sdk: flutter 45 | 46 | # For information on the generic Dart part of this file, see the 47 | # following page: https://dart.dev/tools/pub/pubspec 48 | 49 | # The following section is specific to Flutter. 50 | flutter: 51 | 52 | # The following line ensures that the Material Icons font is 53 | # included with your application, so that you can use the icons in 54 | # the material Icons class. 55 | uses-material-design: true 56 | 57 | # To add assets to your application, add an assets section, like this: 58 | assets: 59 | - assets/audio1.png 60 | - assets/audio2.png 61 | - assets/audio3.png 62 | 63 | # An image asset can refer to one or more resolution-specific "variants", see 64 | # https://flutter.dev/assets-and-images/#resolution-aware. 65 | 66 | # For details regarding adding assets from package dependencies, see 67 | # https://flutter.dev/assets-and-images/#from-packages 68 | 69 | # To add custom fonts to your application, add a fonts section here, 70 | # in this "flutter" section. Each entry in this list should have a 71 | # "family" key with the font family name, and a "fonts" key with a 72 | # list giving the asset and other descriptors for the font. For 73 | # example: 74 | fonts: 75 | - family: Montserrat 76 | fonts: 77 | - asset: fonts/Montserrat-Regular.ttf 78 | - family: Raleway 79 | fonts: 80 | - asset: fonts/Raleway-Regular.ttf 81 | - family: Spartan 82 | fonts: 83 | - asset: fonts/Spartan-Regular.ttf 84 | - family: Poppins 85 | fonts: 86 | - asset: fonts/Poppins-Regular.ttf 87 | # 88 | # For details regarding fonts from package dependencies, 89 | # see https://flutter.dev/custom-fonts/#from-packages 90 | -------------------------------------------------------------------------------- /flutter app/voicefilter/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:voicefilter/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /model/model.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import tensorflow as tf 3 | from tensorflow.keras import Model 4 | from tensorflow.keras.layers import Multiply, ZeroPadding2D, concatenate, Conv2D, Input, Dense, Reshape, BatchNormalization, Activation, LSTM, Bidirectional, Lambda 5 | from Audio import Audio 6 | from HyperParams import HyperParams 7 | 8 | hyper_params = HyperParams() 9 | audio = Audio(hyper_params) 10 | #input dims for model [ T_dim, num_freq ] 11 | T_dim = 301 12 | num_freq = hyper_params.num_freq 13 | emb_dim = hyper_params.embedder_emb_dim 14 | lstm_dim = hyper_params.model_lstm_dim 15 | fc1_dim = hyper_params.model_fc1_dim 16 | fc2_dim = hyper_params.model_fc2_dim #num_freq 17 | batch_size = 8 18 | 19 | def get_model(): 20 | dvec_inp = Input(shape=[emb_dim],name="dvec") 21 | input_spec = Input(shape=[T_dim,num_freq],name="input_spec") 22 | x = Reshape((T_dim,num_freq,1))(input_spec) 23 | 24 | # cnn 25 | 26 | #cnn1 27 | x = ZeroPadding2D(((0,0), (3,3)))(x) 28 | x = Conv2D(filters=64, kernel_size=[1,7], dilation_rate=[1, 1])(x) 29 | x = BatchNormalization()(x) 30 | x = Activation('relu')(x) 31 | #cnn2 32 | x = ZeroPadding2D(((3,3), (0,0)))(x) 33 | x = Conv2D(filters=64, kernel_size=[7,1], dilation_rate=[1, 1])(x) 34 | x = BatchNormalization()(x) 35 | x = Activation('relu')(x) 36 | #cnn3 37 | x = ZeroPadding2D(((2,2), (2,2)))(x) 38 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[1, 1])(x) 39 | x = BatchNormalization()(x) 40 | x = Activation('relu')(x) 41 | #cnn4 42 | x = ZeroPadding2D(((4,4), (2,2)))(x) 43 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[2, 1])(x) 44 | x = BatchNormalization()(x) 45 | x = Activation('relu')(x) 46 | #cnn5 47 | x = ZeroPadding2D(((8,8), (2,2)))(x) 48 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[4, 1])(x) 49 | x = BatchNormalization()(x) 50 | x = Activation('relu')(x) 51 | #cnn6 52 | x = ZeroPadding2D(((16,16), (2,2)))(x) 53 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[8, 1])(x) 54 | x = BatchNormalization()(x) 55 | x = Activation('relu')(x) 56 | #cnn7 57 | x = ZeroPadding2D(((32,32), (2,2)))(x) 58 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[16, 1])(x) 59 | x = BatchNormalization()(x) 60 | x = Activation('relu')(x) 61 | #cnn8 62 | x = Conv2D(filters=8, kernel_size=[1,1], dilation_rate=[1, 1])(x) 63 | x = BatchNormalization()(x) 64 | x = Activation('relu')(x) 65 | 66 | x = Reshape((x.shape[1],x.shape[2]*x.shape[3]))(x) #else use -1 as last arg 67 | #x = tf.reshape(x, [x.shape[0],x.shape[1],-1]) 68 | 69 | dvec = Lambda(lambda a : tf.expand_dims(a,1))(dvec_inp) 70 | dvec = Lambda(lambda a : tf.repeat(a,repeats =x.shape[1],axis =1))(dvec) 71 | #dvec= tf.expand_dims(dvec_inp,1) 72 | #dvec= tf.repeat(dvec,repeats =x.shape[1],axis =1) 73 | 74 | x = concatenate([x,dvec],-1) 75 | #x= tf.concat([x,dvec],-1) 76 | 77 | #lstm 78 | x = Bidirectional(LSTM(lstm_dim,return_sequences=True))(x) 79 | 80 | #fc1 81 | x = Dense(fc1_dim,activation ="relu")(x) 82 | #fc2 83 | mask = Dense(fc2_dim,activation ="sigmoid",name="mask")(x) #soft mask 84 | 85 | #element-wise 86 | output = Multiply()([input_spec,mask]) 87 | 88 | model = Model(inputs=[input_spec,dvec_inp], outputs=output) 89 | 90 | return model -------------------------------------------------------------------------------- /model/sequence_generator.py: -------------------------------------------------------------------------------- 1 | from tensorflow.keras.utils import Sequence 2 | import numpy as np 3 | import os 4 | 5 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset') 6 | path = {} 7 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset') 8 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset') 9 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset') 10 | 11 | 12 | class data_generator(Sequence): 13 | def __init__(self, fraction_sizes , batch_size): 14 | self.batch_size = batch_size 15 | self.fraction_sizes = fraction_sizes 16 | self.num_fractions = len(fraction_sizes) 17 | self.num_samples = sum(self.fraction_sizes) 18 | self.pos = 0 19 | self.cur_fraction = 0 20 | self.input_spec=None 21 | self.output_spec=None 22 | self.dvec=None 23 | def __len__(self): 24 | self.num_batches = 0 25 | for i in range(self.num_fractions): 26 | self.num_batches += (self.fraction_sizes[i]+self.batch_size-1)//self.batch_size 27 | print("len ",self.num_batches) 28 | return self.num_batches 29 | def __getitem__(self,batch_index): 30 | start_pos = self.pos 31 | end_pos = start_pos + self.batch_size 32 | if end_pos > self.fraction_sizes[self.cur_fraction]: 33 | end_pos = self.fraction_sizes[self.cur_fraction] 34 | if start_pos == 0 : 35 | print("loading new data") 36 | if self.input_spec is not None: 37 | print("de allocating old space") 38 | del self.input_spec 39 | del self.output_spec 40 | del self.dvec 41 | indices = np.random.permutation(self.fraction_sizes[self.cur_fraction]) 42 | self.input_spec = np.load(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(self.cur_fraction),'input_spec.npy'))[indices] 43 | self.output_spec = np.load(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(self.cur_fraction),'output_spec.npy'))[indices] 44 | self.dvec = np.load(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(self.cur_fraction),'dvec.npy'))[indices] 45 | print("new data loaded ") 46 | if end_pos == self.fraction_sizes[self.cur_fraction]: 47 | self.cur_fraction += 1 48 | if self.cur_fraction == self.num_fractions: 49 | self.cur_fraction = 0 50 | self.pos = 0 51 | else : 52 | self.pos = end_pos 53 | input_spec_batch = self.input_spec[start_pos:end_pos] 54 | dvector_batch = self.dvec[start_pos:end_pos] 55 | output_spec_batch = self.output_spec[start_pos:end_pos] 56 | return ({'input_spec':input_spec_batch, 'dvec': dvector_batch}, output_spec_batch) 57 | def on_epoch_end(self): 58 | self.pos = 0 59 | self.cur_fraction = 0 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | tensorflow==2.3.0 2 | librosa==0.6.3 3 | numpy==1.18.5 4 | pandas==1.0.5 5 | torch==1.6.0+cu101 6 | matplotlib==3.2.2 7 | mir_eval==0.6 8 | tqdm==4.41.1 -------------------------------------------------------------------------------- /train_test/testing.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from mir_eval.separation import bss_eval_sources 4 | from tqdm import tqdm 5 | import os 6 | import matplotlib.pyplot as plt 7 | 8 | from model import get_model 9 | from HyperParams import HyperParams 10 | from Audio import Audio 11 | 12 | hyper_params = HyperParams 13 | audio = Audio(hyper_params) 14 | batch_size = 8 15 | 16 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset') 17 | path = {} 18 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset') 19 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset') 20 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset') 21 | dataset = 'dev' 22 | 23 | input_spec = np.load(os.path.join(path[dataset],'input_spec.npy')) 24 | input_phase = np.load(os.path.join(path[dataset],'input_phase.npy')) 25 | output_spec = np.load(os.path.join(path[dataset],'output_spec.npy')) 26 | output_phase = np.load(os.path.join(path[dataset],'output_phase.npy')) 27 | dvec = np.load(os.path.join(path[dataset],'dvec.npy')) 28 | 29 | target_waves = [] 30 | for i in tqdm(range(output_spec.shape[0])): 31 | target_waves.append(audio.spec2wave(output_spec[i], output_phase[i])) 32 | val_loss = [] 33 | val_sdr = [] 34 | 35 | model = get_model() 36 | model.compile(optimizer='adam', loss='mse') 37 | 38 | def compute_loss_sdr(weights_path): 39 | model.load_weights(weights_path) 40 | predict_spec = model.predict(x={'input_spec':input_spec,'dvec':dvec} , batch_size = batch_size, verbose = 1) 41 | val_loss.append(np.mean(np.square(output_spec - predict_spec))) 42 | sdr=[] 43 | for i in tqdm(range(predict_spec.shape[0])): 44 | #true_wave = audio.spec2wave(np.load(df_dev['output_spec_path'][i]),np.load(df_dev['output_phase_path'][i])) 45 | predict_wave = audio.spec2wave(predict_spec[i], input_phase[i]) 46 | sdr.append(bss_eval_sources(target_waves[i], predict_wave, False)[0][0]) 47 | val_sdr.append(np.median(np.array(sdr))) 48 | 49 | ### config ### 50 | start_epochs = 1 51 | end_epochs = 6 52 | 53 | for i in range(start_epochs,end_epochs): 54 | weights_path = os.path.join(dataset_path,'Model weights','weights_epoch%04d.h5'%i) 55 | compute_loss_sdr(weights_path) 56 | print() 57 | print(val_loss) 58 | print(val_sdr) 59 | np.save(os.path.join(dataset_path,'val_loss_total_epochs%04d'%(end_epochs-1)),np.array(val_loss)) 60 | np.save(os.path.join(dataset_path,'val_sdr_total_epochs%04d'%(end_epochs-1)),np.array(val_sdr)) 61 | 62 | loss = np.load(os.path.join(path[dataset],'training_loss_total_epochs%04d.npy'%(end_epochs-1))) 63 | 64 | fig , axis = plt.subplots(1,1,figsize = (9,6)) 65 | axis.plot(np.array(range(1,len(loss)+1)),loss,label="training loss") 66 | axis.plot(5*np.array(range(len(val_loss))),val_loss,label="val loss") 67 | axis.legend() 68 | plt.xticks(np.array(range(len(loss)+1))) 69 | plt.xlabel('epoch') 70 | plt.ylabel('loss') 71 | plt.title('Loss') 72 | plt.show() 73 | fig.savefig('loss.png') 74 | 75 | fig , axis = plt.subplots(1,1,figsize = (6,6)) 76 | axis.plot(5*np.array(range(len(val_sdr))), val_sdr, label = "median sdr on val set") 77 | plt.xlabel('epoch') 78 | plt.ylabel('median sdr') 79 | plt.title('SDR on dev set') 80 | plt.show() 81 | fig.savefig('sdr.png') -------------------------------------------------------------------------------- /train_test/train.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | import numpy as np 4 | from tensorflow.keras.callbacks import Callback 5 | from tensorflow.keras.callbacks import ModelCheckpoint 6 | from tqdm import tqdm 7 | 8 | from Audio import Audio 9 | from HyperParams import HyperParams 10 | from model import get_model 11 | from sequence_generator import data_generator 12 | 13 | hyper_params = HyperParams() 14 | audio = Audio(hyper_params) 15 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset') 16 | path = {} 17 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset') 18 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset') 19 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset') 20 | 21 | model = get_model() 22 | model.summary() 23 | 24 | model.compile(optimizer='adam', loss='mse') 25 | 26 | ### execute just once ### 27 | model.save_weights(os.path.join(dataset_path,'Model weights','weights_epoch0000.h5')) 28 | 29 | dataset_train = 'train' 30 | df_train = pd.read_csv(os.path.join(path[dataset_train],'data_frame.csv')) 31 | num_samples = df_train.shape[0] 32 | batch_size = 8 33 | 34 | num_fractions = 8 35 | fraction_sizes = num_fractions * [ num_samples//num_fractions ] 36 | for i in range(num_samples%num_fractions): 37 | fraction_sizes[i]+=1 38 | print(fraction_sizes) 39 | 40 | steps_per_epoch = 0 41 | for i in range(num_fractions): 42 | steps_per_epoch += (fraction_sizes[i]+batch_size-1)//batch_size 43 | print(steps_per_epoch) 44 | 45 | gen_train = data_generator(fraction_sizes, batch_size) 46 | 47 | model_checkpoint_callback = ModelCheckpoint( 48 | os.path.join(dataset_path,'Model weights','weights_epoch{epoch:04d}.h5'),save_weights_only=True) 49 | 50 | ### config ### 51 | initial_epoch = 0 52 | epochs = 20 53 | 54 | hist = model.fit(gen_train, epochs=epochs, verbose=1, steps_per_epoch = 2, shuffle=False, 55 | callbacks=[model_checkpoint_callback 56 | # myCallback() 57 | ] 58 | ) 59 | 60 | loss = hist.history['loss'] 61 | np.save(os.path.join(dataset_path,'training_loss_total_epochs%04d'%epochs),np.array(loss)) 62 | --------------------------------------------------------------------------------