2024년 11월 8일 금요일

시티즈 스카이라인 2 에서 내 도시 다른 사람에게 공유 / 다른 사람의 도시 받기

 영상으로 대신합니다.


먼저, 내 도시를 다른 사람에게 공유하는 방법




다른 사람 도시 받아 불러오는 방법





2024년 8월 11일 일요일

시티즈 스카이라인 2 세이브 폴더 찾기 Where is the "Cities Skylines 2" save files

 사진과 같이 ~


먼저, 폴더 창을 엽니다. 아무 폴더나 상관없음.

폴더창 상단에 보면 주소창이 있는데,

빈 곳을 클릭하면 키보드로 입력할 수 있게 바뀜.


%appdata% 라고 입력


Roaming 폴더로 들어가지는데, 그 상단의 AppData 폴더로 이동 
(아래 사진 참고)


LocalLow 폴더로 들어가기


시티즈 스카이라인 2 제작사인 Colossal Order





들어가면, 긴 숫자로 된 폴더가 하나, 혹은 여러개가 보인다.
실제로는, 스팀 계정 수만큼 폴더가 있는데, 
자기꺼 찾아야 됨.
혼자 쓰는 컴퓨터이면 폴더가 하나일 것.


들어가면
드디어 세이브 파일이 보인다.
이 곳에 다른 세이브 파일을 넣어도 되고
내 것을 여기서 찾아 공유해도 되고.

세이브 하나가 파일 2개로 되어 있음에 유의 ! cok, cid 파일 한쌍이 세이브 하나 !



샘플로 내 최초 100만 인구 달성 도시를 공유한다.


Paradox Mods 로 도시 공유가 가능해졌기 때문에, 그 링크를 먼저 남긴다.

https://mods.paradoxplaza.com/mods/87348/Windows



파일로 받고 싶어하시는 분들을 위해...

원드라이브 링크 : Gilbert_20241027_0017.zip





2024년 6월 30일 일요일

2024년 6월 21일 금요일

자바로 사운드, 음악 파일 (wav) 재생 Play sound or music file (wav) with java codes

 대뜸 예제 첨부

일단 아래와 같은 클래스를 만들어 둔다.


import java.io.File;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
/** Class to play wav file */
public class SoundClip implements Serializable
{
  private static final long serialVersionUID = -4189707921602251694L;
  protected URL    url;
    protected double volume = 100.0;
    protected transient boolean flagStop = false;
    /** Create instance with URL to get wav file */
    public SoundClip(URL url)
    {
     this.url = url;
    }
    /** Create instance with wav file */
    public SoundClip(File f) throws MalformedURLException
    {
     this(f.toURI().toURL());
    }
    /** Play wav sound now */
    public void start()
    {
     if(url == null) return;
     flagStop = false;
     AudioInputStream inp1 = null;
     AudioInputStream inp2 = null;
     SourceDataLine   line = null;
     try
     {
     byte[] buffer = new byte[4096];
         int reads;
        
         // Load wav from URL
         inp1 = AudioSystem.getAudioInputStream(url);
    
         if(flagStop) return; // Return when stop() method called
        
         // Detect audio format of wav file and get converted input stream
     AudioFormat formatBase = inp1.getFormat();
     AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, formatBase.getSampleRate(), 16, formatBase.getChannels(), formatBase.getChannels() * 2, formatBase.getSampleRate(), false);
         inp2 = AudioSystem.getAudioInputStream(format, inp1);
        
         if(flagStop) return; // Return when stop() method called
        
         // Create SourceDataLine to play wav
         DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
         Mixer mixer = AudioSystem.getMixer(null);
         line = (SourceDataLine) mixer.getLine(info);
    
     if(flagStop) return; // Return when stop() method called
    
     // Open SourceDataLine
         line.open(format);
        
         // This must be in here (after line opened !)
     FloatControl ctrl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
ctrl.setValue((float) (20.0f * Math.log10(volume / 100.0)));
        
// Play Start
         line.start();
        
         while(! flagStop)
         {
         reads = inp2.read(buffer, 0, buffer.length);
         if(reads < 0) break; // Return when stop() method called
         line.write(buffer, 0, reads);
         }
        
         // END
         line.drain();
         line.stop();
     }
     catch(Exception ex)
     {
     ex.printStackTrace();
     }
     finally
     {
     try { line.close();  } catch(Exception ex) {}
         try { inp2.close();  } catch(Exception ex) {}
         try { inp1.close();  } catch(Exception ex) {}
         flagStop = false;
     }
    }
    /** Play wav sound now */
public void play()
    {
     start();
    }
/** Stop playing */
    public void stop()
    {
     flagStop = true;
    }
    /** Get volume (0 ~ 100) default 100 */
    public double getVolume()
    {
return volume;
    }
    /** Set volume (0 ~ 100) default 100 */
    public void setVolume(double volume)
    {
this.volume = volume;
if(this.volume < 0) this.volume = 0;
    }
    /** Get URL of wav file */
    public URL getUrl() {
        return url;
    }
    /** Set wav file */
    public void setUrl(URL url) {
        this.url = url;
    }
}



이제 이걸 써먹으면 된다.



File file = new File("fire_beam.wav");
new SoundClip(file.toURI().toURL()).play();



문제가 있는데, 사운드를 재생하는 동안 쓰레드를 독차지하고 있게 된다.

즉, 재생하는 동안 그 아래 코드들은 사운드 재생이 끝날 때까지 실행되지 않는다.

그래서 별도 쓰레드를 많이 만들어 두어서 재생 작업을 쓰레드에서 해야 된다.



2024년 6월 16일 일요일

Beton B-Day - The lesser (Beton B-Day 를 더 쉽게 !)

  기존 Beton Brutal 의 DLC Beton Bath 는 너무 난이도가 어려웠습니다.


Beton Brutal

https://store.steampowered.com/app/2330500/BETON_BRUTAL/


이 Beton Brutal 게임은 Custom Map 기능을 제공합니다.
그리하여, Beton B-Day 낙오자들을 위한 커스텀 맵을 만들었습니다.


Beton B-Day - The lesser










플레이 풀 영상


2024년 6월 10일 월요일

Beton Bath - The lesser (Beton Bath 를 더 쉽게 !)

 기존 Beton Brutal 의 DLC Beton Bath 는 너무 난이도가 어려웠습니다.


Beton Brutal

https://store.steampowered.com/app/2330500/BETON_BRUTAL/


Beton Bath DLC




이 Beton Brutal 게임은 Custom Map 기능을 제공합니다.
그리하여, Beton Bath 낙오자들을 위한 커스텀 맵을 만들었습니다.


Beton Bath - The lesser



기존 Beton Bath 의 몇몇 곳에 트랙을 추가하여, 보다 깨기 쉽게 만들었습니다.










플레이 풀 영상 (마이크 설정 실수로 제 목소리가 이상하게 들어간 것 감안해주세요.)


(브랜드 채널이고 라이브 스트리밍 다시보기라 플레이어 첨부가 안되네요.)


Beton B-Day - The Lesser 도 존재합니다.





2024년 6월 9일 일요일

Elgato Wave Neo 세팅 작업 2024.06.09

Elgato Wave Neo 마이크가 도착하였다.

(구매는 https://smartstore.naver.com/grantree/products/10222370399)






전부 종이박스로 되어있고,
옆면을 마치 과자박스인 양 뜯게 되어있다.

구성품을 하나씩 꺼내본다.
박스 여기저기에 구성품들이 숨어있다.





저 본체 옆 좁은 공간에 기둥과 나사들이 숨어있다.




이제 조립을 시작한다.

먼저, 제공된 나사 중 기다란 것부터 조립한다.
한쪽은 그냥 기다랗게만 되어있고, 다른 한쪽이 나사처럼 나선으로 홈 파져있는 부품이 있는데, 그걸 마이크 본체 쪽에 나선쪽 방향을 넣는다. 손으로 돌려서 넣으면 된다.

아래 사진처럼 되면 잘한거다.



기둥을 바닥파트에 꽂는다. 바닥파트에 작은 홈이 삐죽 나와있고, 기둥파트 바닥에도 홈이 들어가는 구멍이 있다.


남은 나사를 바닥파트 뒷면으로 넣어 돌려서 넣는다.
다 넣으면 손잡이 부분은 옆으로 눌러넣으면 된다.



이제 본체를 기둥파트에 꽂는다. 얘도 저 튀어나온 홈 부분이 들어가는 방향이 정해져 있다.






제공된 USB 케이블을 꽂는다. (아직 PC에 꽂기 전이다. PC에 아직 꽂으면 안 된다.)
꽂는 것도 위아래 방향이 정해져 있다.


이제 소프트웨어를 다운로드 받는다.




WAVE LINK 프로그램을 다운로드 받아 설치한다.


이제 소리가 안들릴 텐데,

게시들 들어가서 제어판 소리 설정과 Voicemeeter Banana 설정을 다시 잡는다.
제어판의 경우 마찬가지로 Voicemeeter Input 과 Voicemeeter Out B3 을 기본 장치로 잡으면 된다.




Voicemeeter Banana 의 경우, 마이크만 잡아주면 된다.
저 Stereo Input 1 부분을 그냥 클릭한다.


Mic in 선택.
(작은 글씨로 Elgato Wave Neo 라고 뜬다.)



이것으로 세팅 끝.



2024년 5월 29일 수요일

HJOW의 투컴방송 세팅 현황 2024.05.29

 먼저 도식도부터 보고 넘어가자.


게임컴에 왜 5800X3D를 안다냐고 할 수 있는데

1. 윈도우7 멀티부팅해서 쓰고 있으나 5800X3D를 달면 윈도우7 부팅하자마자 블루스크린

2. 시티즈 스카이라인 2가 3900X에서 더 성능이 잘 나옴.

이래서 본컴에 3900X 사용 중


RECentral 4 는 스트리밍 없이 녹화만 할 때 사용 중이다. 물론 방송에도 사용할 수는 있다.
RECentral 4는 사용이 쉽고, OBS 대비 부하가 적다.

RECentral 4의 단점은, 상세한 설정이 어렵고, 여러 플랫폼 동시송출 시 녹화 기능을 지원하지 않는다는 것이다. AVerMedia 캡처 카드가 있어야만 쓸 수 있는 프로그램이란 것도 있고.


반면 OBS는 오픈소스 무료 프로그램이라 여러 캡처카드를 지원한다. 설정하는 방법도 너무 복잡한데, 결국 필자가 방송 시에는 OBS를 쓰고 있으므로, 아래쪽에 세팅을 스샷으로 찍어놨다. 이 글을 계속 읽다보면 볼 수 있을 것이다.

결국 전문 스트리머 영역으로 가려면 OBS는 필수라고 할 수 있겠다.



그리고 송출컴에 이슈가 있었는데 해결했다.

어제까지만 해도, 송출 시 전부 x264 (오직 CPU로만 연산함) 으로만 인코딩을 했었다.
어제까지 쓰던 송출컴 GPU는 Radeon RX 550 인데, 이걸로 H264 인코딩 시에도 렉이 걸림.

그래서 녹화를 하면 영상에 렉이 걸리는 사태가 벌어졌음.


오늘 RTX 3050 6G 모델이 도착해 달아줌.



GTX 1660 Super 하고 가격 차이가 얼마 나지도 않길래 그냥 3050 6G 선택.

참고로 요새 송출컴으로 1660 Super 가 흔히 쓰이는 것 같음.
실제로 성능은 1660 Super 가 조금 더 좋다고 함. 그러나 3050쪽이 기능이 많아서 이걸 선택했다. 3050 6G 쪽이 보조전원이 필요가 없다는 것도 한몫 했다.

그리고 3050은 6G 모델과 8G 모델이 있는데, 실제 성능차이도 어마무시하고 가격차이도 어마무시함. 이름 비슷한 것과는 다르게 아예 다른모델이니 주의할 것.

3050 6G 모델의 장점은 별도의 전원선을 연결할 필요가 없다는 것. 그만큼 전기도 덜먹고 발열도 덜 내뿜으며 소음도 덜하다.


이렇게 달아주고, 팬이 캡처카드 뒷면을 갈갈이하지 않도록 지지대를 쬐끔 더 높이 세팅해서 둘의 사이를 벌려주었음. (저 AVerMedia 라고 반짝이는 카드가 캡처카드)


잠시 메인컴으로 돌아와 Voicemeter Banana 를 세팅한다.


Voicemeter Banana 는 도네이션웨어 (무료로 써. 기부할 사람 기부해줘.) 로 공짜로 쓸 수 있는 프로그램이다.
중요한 기능이 있는데, 스피커로 보낼 소리 가져다가, 스피커와 HDMI (송출컴에 연결된) 둘다에게 보낼 수 있게 해 준다. 또한 가상 사운드 장치라는 개념이라 여기에 마이크로 받은 목소리까지 합성해서 보낼 수 있다.



먼저 Voicemeter Banana 설치하고
메인컴 오디오 설정

먼저, 기본 재생 장치를 Voicemeter Input 으로 설정


기본 녹음 장치를 Voicemeter Out B3 으로 설정



그리고 Voicemeter 창 띄워서


이 창에서 하단에 볼륨조절바가 10개가 보인다.
그중 왼쪽에서 4번째 것을 보면, 바로 오른쪽에 여러 버튼들이 보인다.
A1, A2, A3, B1, B2 등등
그중 A1, A3이 반드시 켜져있어야 함.


다시 송출컴으로 넘어가서 OBS 세팅

먼저 방송 세팅 (송출 코덱과 화질 지정)
비디오 인코더는 NVENC HEVC 사용
비트레이트는 12000kbps 지정
그외 설정들 스샷 참고





참고로 H264과 HEVC (=H265) 는 그래픽 카드가 연산을 하고
x264 는 CPU가 연산을 한다.

작업 관리자 열어 성능 탭 들어가면 GPU 사용율을 볼 수 있는데,
GPU 사용율이 너무 높으면 방송 및 녹화 영상에 렉이 들어간다. 
(송출컴 자체에는 렉이 없다.)
반대로 CPU 사용율이 너무 높으면 송출컴 자체에도 렉이 걸린다.
그러므로 일단 GPU부터 80% 가까이 쓰고, 정 안되면 CPU로 넘기는 게 좋다.

방송과 녹화는 별도로 돈다. GPU 사용율이 80%를 넘어간다면, 방송쪽을 CPU로 돌리는 걸 (HEVC 대신 x264 사용) 고려해야 한다.
보통 녹화를 더 고화질로 하기 때문에, 녹화만큼은 GPU로 하는 게 좋다.

이글 계속 보다보면 아래쪽에 동시송출 플러그인 설정하는 파트가 있는데
거기도 마찬가지다. GPU 부하가 너무 크다면 CPU로 돌리는 선택을 한다.

비트레이트는 그냥 높을수록 화질이 좋다고 보면 된다.
같은 풀HD라도 비트레이트가 낮으면 화면이 자글자글해진다.
풀HD 기준 15000kbps 이면 아주 깔끔한 화질이 나온다. 
하지만 
15000kbps 로 설정 시 부하가 너무 크고, 파일 용량도 커지며, 무엇보다,
유튜브 스트리밍 시 유튜브 서버에서 이 화질을 제대로 출력도 못하고 
(공식 12000kbps 권장)
치지직은 8000kbps 초과로 설정 시 아예 방송이 되지 않는다.



다시 설정으로 돌아와서...



녹화 탭
녹화 (파일로 저장) 코덱과 화질 지정
이것도 NVENC HEVC 사용
방송 탭과 마찬가지로 12000kbps

오디오 비트레이트 192 나머지는 그대로


샘플 레이트 48kHz 나머지는 기본값


풀HD 60프레임 설정



고급 탭에서 스트림 지연 설정 (지금은 사용하지 않음)
(오디오 딜레이 해결하려고 넣은건데, 다시 빼도 괜찮길래 지금은 활성화 해제해 놓았다.)


그리고 동시송출 플러그인 세팅
치지직은 H264 세팅 시 화면이 안나오더라. 그냥 x264 유지.



이렇게 세팅해서 종합적으로 보면



송출컴 화면이 대략 이런 양상이 펼쳐진다.
여기서 우측하단 작업 관리자만 확대해 보면



100% 찍는 게 하나도 없다. GPU도 73% 언저리에서 여유있게 일하는 중

태블릿으로 치지직하고 유튜브 접속해 모니터링 해봤는데 역시 렉이 발견되지 않았다.
녹화된거 재생해보니 마찬가지로 렉이 없었다.



비트레이트도 10000을 넘어가는거 보니 별도 세팅이 잘 먹고 있다.
(치지직은 10000 넘어가면 치지직 알림 오면서 방송 5분 정지된다. 정지가 안됐다는 건 유튜브는 고화질로 치지직만 별도 세팅으로 잘 동작하고 있다는 뜻이다.)

일단 이러한 세팅으로 방송 시 오디오 딜레이도 없고 렉도 발견되지 않았다.
녹화도 된다. 판타스틱 ~

저 2초 딜레이 결국 뺐다. 오디오 딜레이 늘어나지 않아 이대로 가도 될 듯 하다.