package com.lemenzo.clock.bedtime;
import android.app.*;import android.content.*;import android.media.*;import android.os.*;import com.lemenzo.clock.R;import com.lemenzo.clock.notifications.NotificationChannels;import java.util.Random;
public final class SleepSoundService extends android.app.Service {public static final String EXTRA_MODE="mode",MODE_BROWN="brown",MODE_PINK="pink";private static volatile boolean active=false;private AudioTrack track;private Thread worker;public static boolean isActive(){return active;}@Override public int onStartCommand(Intent i,int flags,int startId){String mode=i==null?MODE_BROWN:i.getStringExtra(EXTRA_MODE);startForeground(4401,new Notification.Builder(this,NotificationChannels.SLEEP).setSmallIcon(R.drawable.ic_notification_clock).setContentTitle(getString(R.string.sleep_sounds)).setContentText(getString(R.string.sleep_sound_running)).setOngoing(true).build());startNoise(MODE_PINK.equals(mode));return START_NOT_STICKY;}private void startNoise(boolean pink){stopNoise();int rate=22050,min=AudioTrack.getMinBufferSize(rate,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);track=new AudioTrack.Builder().setAudioAttributes(new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()).setAudioFormat(new AudioFormat.Builder().setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(rate).setChannelMask(AudioFormat.CHANNEL_OUT_MONO).build()).setBufferSizeInBytes(Math.max(min,rate)).setTransferMode(AudioTrack.MODE_STREAM).build();active=true;track.play();worker=new Thread(()->{Random r=new Random();short[] b=new short[1024];double brown=0,pinkState=0;while(active&&!Thread.currentThread().isInterrupted()){for(int x=0;x<b.length;x++){double white=r.nextDouble()*2-1;if(pink){pinkState=.985*pinkState+.015*white;b[x]=(short)(Math.max(-1,Math.min(1,pinkState*4))*5000);}else{brown=(brown+.02*white)/1.02;b[x]=(short)(Math.max(-1,Math.min(1,brown*3.5))*5500);}}if(track!=null)track.write(b,0,b.length,AudioTrack.WRITE_BLOCKING);}},"LemenzoSleepSound");worker.start();}private void stopNoise(){active=false;if(worker!=null){worker.interrupt();worker=null;}if(track!=null){try{track.stop();}catch(Exception ignored){}track.release();track=null;}}@Override public void onDestroy(){stopNoise();stopForeground(STOP_FOREGROUND_REMOVE);super.onDestroy();}@Override public IBinder onBind(Intent i){return null;}}
